6 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
8 * Copyright (c) 2001-2003 Maksim Yevmenkin <m_evmenkin@yahoo.com>
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
20 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 * $Id: ng_btsocket_rfcomm.c,v 1.28 2003/09/14 23:29:06 max Exp $
36 #include <sys/param.h>
37 #include <sys/systm.h>
38 #include <sys/bitstring.h>
39 #include <sys/domain.h>
40 #include <sys/endian.h>
41 #include <sys/errno.h>
42 #include <sys/filedesc.h>
43 #include <sys/ioccom.h>
44 #include <sys/kernel.h>
46 #include <sys/malloc.h>
48 #include <sys/mutex.h>
50 #include <sys/protosw.h>
51 #include <sys/queue.h>
52 #include <sys/socket.h>
53 #include <sys/socketvar.h>
54 #include <sys/sysctl.h>
55 #include <sys/taskqueue.h>
60 #include <netgraph/ng_message.h>
61 #include <netgraph/netgraph.h>
62 #include <netgraph/bluetooth/include/ng_bluetooth.h>
63 #include <netgraph/bluetooth/include/ng_hci.h>
64 #include <netgraph/bluetooth/include/ng_l2cap.h>
65 #include <netgraph/bluetooth/include/ng_btsocket.h>
66 #include <netgraph/bluetooth/include/ng_btsocket_l2cap.h>
67 #include <netgraph/bluetooth/include/ng_btsocket_rfcomm.h>
70 #ifdef NG_SEPARATE_MALLOC
71 static MALLOC_DEFINE(M_NETGRAPH_BTSOCKET_RFCOMM, "netgraph_btsocks_rfcomm",
72 "Netgraph Bluetooth RFCOMM sockets");
74 #define M_NETGRAPH_BTSOCKET_RFCOMM M_NETGRAPH
75 #endif /* NG_SEPARATE_MALLOC */
78 #define NG_BTSOCKET_RFCOMM_INFO \
79 if (ng_btsocket_rfcomm_debug_level >= NG_BTSOCKET_INFO_LEVEL && \
80 ppsratecheck(&ng_btsocket_rfcomm_lasttime, &ng_btsocket_rfcomm_curpps, 1)) \
83 #define NG_BTSOCKET_RFCOMM_WARN \
84 if (ng_btsocket_rfcomm_debug_level >= NG_BTSOCKET_WARN_LEVEL && \
85 ppsratecheck(&ng_btsocket_rfcomm_lasttime, &ng_btsocket_rfcomm_curpps, 1)) \
88 #define NG_BTSOCKET_RFCOMM_ERR \
89 if (ng_btsocket_rfcomm_debug_level >= NG_BTSOCKET_ERR_LEVEL && \
90 ppsratecheck(&ng_btsocket_rfcomm_lasttime, &ng_btsocket_rfcomm_curpps, 1)) \
93 #define NG_BTSOCKET_RFCOMM_ALERT \
94 if (ng_btsocket_rfcomm_debug_level >= NG_BTSOCKET_ALERT_LEVEL && \
95 ppsratecheck(&ng_btsocket_rfcomm_lasttime, &ng_btsocket_rfcomm_curpps, 1)) \
100 /* Local prototypes */
101 static int ng_btsocket_rfcomm_upcall
102 (struct socket *so, void *arg, int waitflag);
103 static void ng_btsocket_rfcomm_sessions_task
104 (void *ctx, int pending);
105 static void ng_btsocket_rfcomm_session_task
106 (ng_btsocket_rfcomm_session_p s);
107 #define ng_btsocket_rfcomm_task_wakeup() \
108 taskqueue_enqueue(taskqueue_swi_giant, &ng_btsocket_rfcomm_task)
110 static ng_btsocket_rfcomm_pcb_p ng_btsocket_rfcomm_connect_ind
111 (ng_btsocket_rfcomm_session_p s, int channel);
112 static void ng_btsocket_rfcomm_connect_cfm
113 (ng_btsocket_rfcomm_session_p s);
115 static int ng_btsocket_rfcomm_session_create
116 (ng_btsocket_rfcomm_session_p *sp, struct socket *l2so,
117 bdaddr_p src, bdaddr_p dst, struct thread *td);
118 static int ng_btsocket_rfcomm_session_accept
119 (ng_btsocket_rfcomm_session_p s0);
120 static int ng_btsocket_rfcomm_session_connect
121 (ng_btsocket_rfcomm_session_p s);
122 static int ng_btsocket_rfcomm_session_receive
123 (ng_btsocket_rfcomm_session_p s);
124 static int ng_btsocket_rfcomm_session_send
125 (ng_btsocket_rfcomm_session_p s);
126 static void ng_btsocket_rfcomm_session_clean
127 (ng_btsocket_rfcomm_session_p s);
128 static void ng_btsocket_rfcomm_session_process_pcb
129 (ng_btsocket_rfcomm_session_p s);
130 static ng_btsocket_rfcomm_session_p ng_btsocket_rfcomm_session_by_addr
131 (bdaddr_p src, bdaddr_p dst);
133 static int ng_btsocket_rfcomm_receive_frame
134 (ng_btsocket_rfcomm_session_p s, struct mbuf *m0);
135 static int ng_btsocket_rfcomm_receive_sabm
136 (ng_btsocket_rfcomm_session_p s, int dlci);
137 static int ng_btsocket_rfcomm_receive_disc
138 (ng_btsocket_rfcomm_session_p s, int dlci);
139 static int ng_btsocket_rfcomm_receive_ua
140 (ng_btsocket_rfcomm_session_p s, int dlci);
141 static int ng_btsocket_rfcomm_receive_dm
142 (ng_btsocket_rfcomm_session_p s, int dlci);
143 static int ng_btsocket_rfcomm_receive_uih
144 (ng_btsocket_rfcomm_session_p s, int dlci, int pf, struct mbuf *m0);
145 static int ng_btsocket_rfcomm_receive_mcc
146 (ng_btsocket_rfcomm_session_p s, struct mbuf *m0);
147 static int ng_btsocket_rfcomm_receive_test
148 (ng_btsocket_rfcomm_session_p s, struct mbuf *m0);
149 static int ng_btsocket_rfcomm_receive_fc
150 (ng_btsocket_rfcomm_session_p s, struct mbuf *m0);
151 static int ng_btsocket_rfcomm_receive_msc
152 (ng_btsocket_rfcomm_session_p s, struct mbuf *m0);
153 static int ng_btsocket_rfcomm_receive_rpn
154 (ng_btsocket_rfcomm_session_p s, struct mbuf *m0);
155 static int ng_btsocket_rfcomm_receive_rls
156 (ng_btsocket_rfcomm_session_p s, struct mbuf *m0);
157 static int ng_btsocket_rfcomm_receive_pn
158 (ng_btsocket_rfcomm_session_p s, struct mbuf *m0);
159 static void ng_btsocket_rfcomm_set_pn
160 (ng_btsocket_rfcomm_pcb_p pcb, u_int8_t cr, u_int8_t flow_control,
161 u_int8_t credits, u_int16_t mtu);
163 static int ng_btsocket_rfcomm_send_command
164 (ng_btsocket_rfcomm_session_p s, u_int8_t type, u_int8_t dlci);
165 static int ng_btsocket_rfcomm_send_uih
166 (ng_btsocket_rfcomm_session_p s, u_int8_t address, u_int8_t pf,
167 u_int8_t credits, struct mbuf *data);
168 static int ng_btsocket_rfcomm_send_msc
169 (ng_btsocket_rfcomm_pcb_p pcb);
170 static int ng_btsocket_rfcomm_send_pn
171 (ng_btsocket_rfcomm_pcb_p pcb);
172 static int ng_btsocket_rfcomm_send_credits
173 (ng_btsocket_rfcomm_pcb_p pcb);
175 static int ng_btsocket_rfcomm_pcb_send
176 (ng_btsocket_rfcomm_pcb_p pcb, int limit);
177 static void ng_btsocket_rfcomm_pcb_kill
178 (ng_btsocket_rfcomm_pcb_p pcb, int error);
179 static ng_btsocket_rfcomm_pcb_p ng_btsocket_rfcomm_pcb_by_dlci
180 (ng_btsocket_rfcomm_session_p s, int dlci);
181 static ng_btsocket_rfcomm_pcb_p ng_btsocket_rfcomm_pcb_listener
182 (bdaddr_p src, int channel);
184 static void ng_btsocket_rfcomm_timeout
185 (ng_btsocket_rfcomm_pcb_p pcb);
186 static void ng_btsocket_rfcomm_untimeout
187 (ng_btsocket_rfcomm_pcb_p pcb);
188 static void ng_btsocket_rfcomm_process_timeout
191 static struct mbuf * ng_btsocket_rfcomm_prepare_packet
192 (struct sockbuf *sb, int length);
195 extern int ifqmaxlen;
196 static u_int32_t ng_btsocket_rfcomm_debug_level;
197 static u_int32_t ng_btsocket_rfcomm_timo;
198 struct task ng_btsocket_rfcomm_task;
199 static LIST_HEAD(, ng_btsocket_rfcomm_session) ng_btsocket_rfcomm_sessions;
200 static struct mtx ng_btsocket_rfcomm_sessions_mtx;
201 static LIST_HEAD(, ng_btsocket_rfcomm_pcb) ng_btsocket_rfcomm_sockets;
202 static struct mtx ng_btsocket_rfcomm_sockets_mtx;
203 static struct timeval ng_btsocket_rfcomm_lasttime;
204 static int ng_btsocket_rfcomm_curpps;
207 SYSCTL_DECL(_net_bluetooth_rfcomm_sockets);
208 static SYSCTL_NODE(_net_bluetooth_rfcomm_sockets, OID_AUTO, stream,
209 CTLFLAG_RW | CTLFLAG_MPSAFE, 0,
210 "Bluetooth STREAM RFCOMM sockets family");
211 SYSCTL_UINT(_net_bluetooth_rfcomm_sockets_stream, OID_AUTO, debug_level,
213 &ng_btsocket_rfcomm_debug_level, NG_BTSOCKET_INFO_LEVEL,
214 "Bluetooth STREAM RFCOMM sockets debug level");
215 SYSCTL_UINT(_net_bluetooth_rfcomm_sockets_stream, OID_AUTO, timeout,
217 &ng_btsocket_rfcomm_timo, 60,
218 "Bluetooth STREAM RFCOMM sockets timeout");
220 /*****************************************************************************
221 *****************************************************************************
223 *****************************************************************************
224 *****************************************************************************/
226 static u_int8_t ng_btsocket_rfcomm_crc_table[256] = {
227 0x00, 0x91, 0xe3, 0x72, 0x07, 0x96, 0xe4, 0x75,
228 0x0e, 0x9f, 0xed, 0x7c, 0x09, 0x98, 0xea, 0x7b,
229 0x1c, 0x8d, 0xff, 0x6e, 0x1b, 0x8a, 0xf8, 0x69,
230 0x12, 0x83, 0xf1, 0x60, 0x15, 0x84, 0xf6, 0x67,
232 0x38, 0xa9, 0xdb, 0x4a, 0x3f, 0xae, 0xdc, 0x4d,
233 0x36, 0xa7, 0xd5, 0x44, 0x31, 0xa0, 0xd2, 0x43,
234 0x24, 0xb5, 0xc7, 0x56, 0x23, 0xb2, 0xc0, 0x51,
235 0x2a, 0xbb, 0xc9, 0x58, 0x2d, 0xbc, 0xce, 0x5f,
237 0x70, 0xe1, 0x93, 0x02, 0x77, 0xe6, 0x94, 0x05,
238 0x7e, 0xef, 0x9d, 0x0c, 0x79, 0xe8, 0x9a, 0x0b,
239 0x6c, 0xfd, 0x8f, 0x1e, 0x6b, 0xfa, 0x88, 0x19,
240 0x62, 0xf3, 0x81, 0x10, 0x65, 0xf4, 0x86, 0x17,
242 0x48, 0xd9, 0xab, 0x3a, 0x4f, 0xde, 0xac, 0x3d,
243 0x46, 0xd7, 0xa5, 0x34, 0x41, 0xd0, 0xa2, 0x33,
244 0x54, 0xc5, 0xb7, 0x26, 0x53, 0xc2, 0xb0, 0x21,
245 0x5a, 0xcb, 0xb9, 0x28, 0x5d, 0xcc, 0xbe, 0x2f,
247 0xe0, 0x71, 0x03, 0x92, 0xe7, 0x76, 0x04, 0x95,
248 0xee, 0x7f, 0x0d, 0x9c, 0xe9, 0x78, 0x0a, 0x9b,
249 0xfc, 0x6d, 0x1f, 0x8e, 0xfb, 0x6a, 0x18, 0x89,
250 0xf2, 0x63, 0x11, 0x80, 0xf5, 0x64, 0x16, 0x87,
252 0xd8, 0x49, 0x3b, 0xaa, 0xdf, 0x4e, 0x3c, 0xad,
253 0xd6, 0x47, 0x35, 0xa4, 0xd1, 0x40, 0x32, 0xa3,
254 0xc4, 0x55, 0x27, 0xb6, 0xc3, 0x52, 0x20, 0xb1,
255 0xca, 0x5b, 0x29, 0xb8, 0xcd, 0x5c, 0x2e, 0xbf,
257 0x90, 0x01, 0x73, 0xe2, 0x97, 0x06, 0x74, 0xe5,
258 0x9e, 0x0f, 0x7d, 0xec, 0x99, 0x08, 0x7a, 0xeb,
259 0x8c, 0x1d, 0x6f, 0xfe, 0x8b, 0x1a, 0x68, 0xf9,
260 0x82, 0x13, 0x61, 0xf0, 0x85, 0x14, 0x66, 0xf7,
262 0xa8, 0x39, 0x4b, 0xda, 0xaf, 0x3e, 0x4c, 0xdd,
263 0xa6, 0x37, 0x45, 0xd4, 0xa1, 0x30, 0x42, 0xd3,
264 0xb4, 0x25, 0x57, 0xc6, 0xb3, 0x22, 0x50, 0xc1,
265 0xba, 0x2b, 0x59, 0xc8, 0xbd, 0x2c, 0x5e, 0xcf
270 ng_btsocket_rfcomm_crc(u_int8_t *data, int length)
275 crc = ng_btsocket_rfcomm_crc_table[crc ^ *data++];
278 } /* ng_btsocket_rfcomm_crc */
282 ng_btsocket_rfcomm_fcs2(u_int8_t *data)
284 return (0xff - ng_btsocket_rfcomm_crc(data, 2));
285 } /* ng_btsocket_rfcomm_fcs2 */
289 ng_btsocket_rfcomm_fcs3(u_int8_t *data)
291 return (0xff - ng_btsocket_rfcomm_crc(data, 3));
292 } /* ng_btsocket_rfcomm_fcs3 */
297 * From Bluetooth spec
299 * "... In 07.10, the frame check sequence (FCS) is calculated on different
300 * sets of fields for different frame types. These are the fields that the
301 * FCS are calculated on:
303 * For SABM, DISC, UA, DM frames: on Address, Control and length field.
304 * For UIH frames: on Address and Control field.
306 * (This is stated here for clarification, and to set the standard for RFCOMM;
307 * the fields included in FCS calculation have actually changed in version
308 * 7.0.0 of TS 07.10, but RFCOMM will not change the FCS calculation scheme
309 * from the one above.) ..."
313 ng_btsocket_rfcomm_check_fcs(u_int8_t *data, int type, u_int8_t fcs)
315 if (type != RFCOMM_FRAME_UIH)
316 return (ng_btsocket_rfcomm_fcs3(data) != fcs);
318 return (ng_btsocket_rfcomm_fcs2(data) != fcs);
319 } /* ng_btsocket_rfcomm_check_fcs */
321 /*****************************************************************************
322 *****************************************************************************
324 *****************************************************************************
325 *****************************************************************************/
328 * Initialize everything
332 ng_btsocket_rfcomm_init(void)
335 /* Skip initialization of globals for non-default instances. */
336 if (!IS_DEFAULT_VNET(curvnet))
339 ng_btsocket_rfcomm_debug_level = NG_BTSOCKET_WARN_LEVEL;
340 ng_btsocket_rfcomm_timo = 60;
343 TASK_INIT(&ng_btsocket_rfcomm_task, 0,
344 ng_btsocket_rfcomm_sessions_task, NULL);
346 /* RFCOMM sessions list */
347 LIST_INIT(&ng_btsocket_rfcomm_sessions);
348 mtx_init(&ng_btsocket_rfcomm_sessions_mtx,
349 "btsocks_rfcomm_sessions_mtx", NULL, MTX_DEF);
351 /* RFCOMM sockets list */
352 LIST_INIT(&ng_btsocket_rfcomm_sockets);
353 mtx_init(&ng_btsocket_rfcomm_sockets_mtx,
354 "btsocks_rfcomm_sockets_mtx", NULL, MTX_DEF);
355 } /* ng_btsocket_rfcomm_init */
358 * Abort connection on socket
362 ng_btsocket_rfcomm_abort(struct socket *so)
365 so->so_error = ECONNABORTED;
366 (void)ng_btsocket_rfcomm_disconnect(so);
367 } /* ng_btsocket_rfcomm_abort */
370 ng_btsocket_rfcomm_close(struct socket *so)
373 (void)ng_btsocket_rfcomm_disconnect(so);
374 } /* ng_btsocket_rfcomm_close */
377 * Accept connection on socket. Nothing to do here, socket must be connected
378 * and ready, so just return peer address and be done with it.
382 ng_btsocket_rfcomm_accept(struct socket *so, struct sockaddr **nam)
384 return (ng_btsocket_rfcomm_peeraddr(so, nam));
385 } /* ng_btsocket_rfcomm_accept */
388 * Create and attach new socket
392 ng_btsocket_rfcomm_attach(struct socket *so, int proto, struct thread *td)
394 ng_btsocket_rfcomm_pcb_p pcb = so2rfcomm_pcb(so);
397 /* Check socket and protocol */
398 if (so->so_type != SOCK_STREAM)
399 return (ESOCKTNOSUPPORT);
401 #if 0 /* XXX sonewconn() calls "pru_attach" with proto == 0 */
403 if (proto != BLUETOOTH_PROTO_RFCOMM)
404 return (EPROTONOSUPPORT);
410 /* Reserve send and receive space if it is not reserved yet */
411 if ((so->so_snd.sb_hiwat == 0) || (so->so_rcv.sb_hiwat == 0)) {
412 error = soreserve(so, NG_BTSOCKET_RFCOMM_SENDSPACE,
413 NG_BTSOCKET_RFCOMM_RECVSPACE);
418 /* Allocate the PCB */
419 pcb = malloc(sizeof(*pcb),
420 M_NETGRAPH_BTSOCKET_RFCOMM, M_NOWAIT | M_ZERO);
424 /* Link the PCB and the socket */
425 so->so_pcb = (caddr_t) pcb;
429 pcb->state = NG_BTSOCKET_RFCOMM_DLC_CLOSED;
430 pcb->flags = NG_BTSOCKET_RFCOMM_DLC_CFC;
433 pcb->rmodem = (RFCOMM_MODEM_RTC | RFCOMM_MODEM_RTR | RFCOMM_MODEM_DV);
435 pcb->mtu = RFCOMM_DEFAULT_MTU;
437 pcb->rx_cred = RFCOMM_DEFAULT_CREDITS;
439 mtx_init(&pcb->pcb_mtx, "btsocks_rfcomm_pcb_mtx", NULL, MTX_DEF);
440 callout_init_mtx(&pcb->timo, &pcb->pcb_mtx, 0);
442 /* Add the PCB to the list */
443 mtx_lock(&ng_btsocket_rfcomm_sockets_mtx);
444 LIST_INSERT_HEAD(&ng_btsocket_rfcomm_sockets, pcb, next);
445 mtx_unlock(&ng_btsocket_rfcomm_sockets_mtx);
448 } /* ng_btsocket_rfcomm_attach */
455 ng_btsocket_rfcomm_bind(struct socket *so, struct sockaddr *nam,
458 ng_btsocket_rfcomm_pcb_t *pcb = so2rfcomm_pcb(so), *pcb1;
459 struct sockaddr_rfcomm *sa = (struct sockaddr_rfcomm *) nam;
467 if (sa->rfcomm_family != AF_BLUETOOTH)
468 return (EAFNOSUPPORT);
469 if (sa->rfcomm_len != sizeof(*sa))
471 if (sa->rfcomm_channel > 30)
474 mtx_lock(&pcb->pcb_mtx);
476 if (sa->rfcomm_channel != 0) {
477 mtx_lock(&ng_btsocket_rfcomm_sockets_mtx);
479 LIST_FOREACH(pcb1, &ng_btsocket_rfcomm_sockets, next) {
480 if (pcb1->channel == sa->rfcomm_channel &&
481 bcmp(&pcb1->src, &sa->rfcomm_bdaddr,
482 sizeof(pcb1->src)) == 0) {
483 mtx_unlock(&ng_btsocket_rfcomm_sockets_mtx);
484 mtx_unlock(&pcb->pcb_mtx);
490 mtx_unlock(&ng_btsocket_rfcomm_sockets_mtx);
493 bcopy(&sa->rfcomm_bdaddr, &pcb->src, sizeof(pcb->src));
494 pcb->channel = sa->rfcomm_channel;
496 mtx_unlock(&pcb->pcb_mtx);
499 } /* ng_btsocket_rfcomm_bind */
506 ng_btsocket_rfcomm_connect(struct socket *so, struct sockaddr *nam,
509 ng_btsocket_rfcomm_pcb_t *pcb = so2rfcomm_pcb(so);
510 struct sockaddr_rfcomm *sa = (struct sockaddr_rfcomm *) nam;
511 ng_btsocket_rfcomm_session_t *s = NULL;
512 struct socket *l2so = NULL;
521 if (sa->rfcomm_family != AF_BLUETOOTH)
522 return (EAFNOSUPPORT);
523 if (sa->rfcomm_len != sizeof(*sa))
525 if (sa->rfcomm_channel > 30)
527 if (sa->rfcomm_channel == 0 ||
528 bcmp(&sa->rfcomm_bdaddr, NG_HCI_BDADDR_ANY, sizeof(bdaddr_t)) == 0)
529 return (EDESTADDRREQ);
532 * Note that we will not check for errors in socreate() because
533 * if we failed to create L2CAP socket at this point we still
534 * might have already open session.
537 error = socreate(PF_BLUETOOTH, &l2so, SOCK_SEQPACKET,
538 BLUETOOTH_PROTO_L2CAP, td->td_ucred, td);
541 * Look for session between "pcb->src" and "sa->rfcomm_bdaddr" (dst)
544 mtx_lock(&ng_btsocket_rfcomm_sessions_mtx);
546 s = ng_btsocket_rfcomm_session_by_addr(&pcb->src, &sa->rfcomm_bdaddr);
549 * We need to create new RFCOMM session. Check if we have L2CAP
550 * socket. If l2so == NULL then error has the error code from
555 mtx_unlock(&ng_btsocket_rfcomm_sessions_mtx);
559 error = ng_btsocket_rfcomm_session_create(&s, l2so,
560 &pcb->src, &sa->rfcomm_bdaddr, td);
562 mtx_unlock(&ng_btsocket_rfcomm_sessions_mtx);
567 } else if (l2so != NULL)
568 soclose(l2so); /* we don't need new L2CAP socket */
571 * Check if we already have the same DLCI the same session
574 mtx_lock(&s->session_mtx);
575 mtx_lock(&pcb->pcb_mtx);
577 dlci = RFCOMM_MKDLCI(!INITIATOR(s), sa->rfcomm_channel);
579 if (ng_btsocket_rfcomm_pcb_by_dlci(s, dlci) != NULL) {
580 mtx_unlock(&pcb->pcb_mtx);
581 mtx_unlock(&s->session_mtx);
582 mtx_unlock(&ng_btsocket_rfcomm_sessions_mtx);
588 * Check session state and if its not acceptable then refuse connection
592 case NG_BTSOCKET_RFCOMM_SESSION_CONNECTING:
593 case NG_BTSOCKET_RFCOMM_SESSION_CONNECTED:
594 case NG_BTSOCKET_RFCOMM_SESSION_OPEN:
596 * Update destination address and channel and attach
600 bcopy(&sa->rfcomm_bdaddr, &pcb->dst, sizeof(pcb->dst));
601 pcb->channel = sa->rfcomm_channel;
604 LIST_INSERT_HEAD(&s->dlcs, pcb, session_next);
607 ng_btsocket_rfcomm_timeout(pcb);
608 soisconnecting(pcb->so);
610 if (s->state == NG_BTSOCKET_RFCOMM_SESSION_OPEN) {
612 bcopy(&so2l2cap_pcb(s->l2so)->src, &pcb->src,
615 pcb->state = NG_BTSOCKET_RFCOMM_DLC_CONFIGURING;
617 error = ng_btsocket_rfcomm_send_pn(pcb);
619 error = ng_btsocket_rfcomm_task_wakeup();
621 pcb->state = NG_BTSOCKET_RFCOMM_DLC_W4_CONNECT;
629 mtx_unlock(&pcb->pcb_mtx);
630 mtx_unlock(&s->session_mtx);
631 mtx_unlock(&ng_btsocket_rfcomm_sessions_mtx);
634 } /* ng_btsocket_rfcomm_connect */
637 * Process ioctl's calls on socket.
638 * XXX FIXME this should provide interface to the RFCOMM multiplexor channel
642 ng_btsocket_rfcomm_control(struct socket *so, u_long cmd, caddr_t data,
643 struct ifnet *ifp, struct thread *td)
646 } /* ng_btsocket_rfcomm_control */
649 * Process getsockopt/setsockopt system calls
653 ng_btsocket_rfcomm_ctloutput(struct socket *so, struct sockopt *sopt)
655 ng_btsocket_rfcomm_pcb_p pcb = so2rfcomm_pcb(so);
656 struct ng_btsocket_rfcomm_fc_info fcinfo;
661 if (sopt->sopt_level != SOL_RFCOMM)
664 mtx_lock(&pcb->pcb_mtx);
666 switch (sopt->sopt_dir) {
668 switch (sopt->sopt_name) {
670 error = sooptcopyout(sopt, &pcb->mtu, sizeof(pcb->mtu));
673 case SO_RFCOMM_FC_INFO:
674 fcinfo.lmodem = pcb->lmodem;
675 fcinfo.rmodem = pcb->rmodem;
676 fcinfo.tx_cred = pcb->tx_cred;
677 fcinfo.rx_cred = pcb->rx_cred;
678 fcinfo.cfc = (pcb->flags & NG_BTSOCKET_RFCOMM_DLC_CFC)?
682 error = sooptcopyout(sopt, &fcinfo, sizeof(fcinfo));
692 switch (sopt->sopt_name) {
704 mtx_unlock(&pcb->pcb_mtx);
707 } /* ng_btsocket_rfcomm_ctloutput */
710 * Detach and destroy socket
714 ng_btsocket_rfcomm_detach(struct socket *so)
716 ng_btsocket_rfcomm_pcb_p pcb = so2rfcomm_pcb(so);
718 KASSERT(pcb != NULL, ("ng_btsocket_rfcomm_detach: pcb == NULL"));
720 mtx_lock(&pcb->pcb_mtx);
722 switch (pcb->state) {
723 case NG_BTSOCKET_RFCOMM_DLC_W4_CONNECT:
724 case NG_BTSOCKET_RFCOMM_DLC_CONFIGURING:
725 case NG_BTSOCKET_RFCOMM_DLC_CONNECTING:
726 case NG_BTSOCKET_RFCOMM_DLC_CONNECTED:
727 /* XXX What to do with pending request? */
728 if (pcb->flags & NG_BTSOCKET_RFCOMM_DLC_TIMO)
729 ng_btsocket_rfcomm_untimeout(pcb);
731 if (pcb->state == NG_BTSOCKET_RFCOMM_DLC_W4_CONNECT)
732 pcb->flags |= NG_BTSOCKET_RFCOMM_DLC_DETACHED;
734 pcb->state = NG_BTSOCKET_RFCOMM_DLC_DISCONNECTING;
736 ng_btsocket_rfcomm_task_wakeup();
739 case NG_BTSOCKET_RFCOMM_DLC_DISCONNECTING:
740 ng_btsocket_rfcomm_task_wakeup();
744 while (pcb->state != NG_BTSOCKET_RFCOMM_DLC_CLOSED)
745 msleep(&pcb->state, &pcb->pcb_mtx, PZERO, "rf_det", 0);
747 if (pcb->session != NULL)
748 panic("%s: pcb->session != NULL\n", __func__);
749 if (pcb->flags & NG_BTSOCKET_RFCOMM_DLC_TIMO)
750 panic("%s: timeout on closed DLC, flags=%#x\n",
751 __func__, pcb->flags);
753 mtx_lock(&ng_btsocket_rfcomm_sockets_mtx);
754 LIST_REMOVE(pcb, next);
755 mtx_unlock(&ng_btsocket_rfcomm_sockets_mtx);
757 mtx_unlock(&pcb->pcb_mtx);
759 mtx_destroy(&pcb->pcb_mtx);
760 bzero(pcb, sizeof(*pcb));
761 free(pcb, M_NETGRAPH_BTSOCKET_RFCOMM);
763 soisdisconnected(so);
765 } /* ng_btsocket_rfcomm_detach */
772 ng_btsocket_rfcomm_disconnect(struct socket *so)
774 ng_btsocket_rfcomm_pcb_p pcb = so2rfcomm_pcb(so);
779 mtx_lock(&pcb->pcb_mtx);
781 if (pcb->state == NG_BTSOCKET_RFCOMM_DLC_DISCONNECTING) {
782 mtx_unlock(&pcb->pcb_mtx);
783 return (EINPROGRESS);
786 /* XXX What to do with pending request? */
787 if (pcb->flags & NG_BTSOCKET_RFCOMM_DLC_TIMO)
788 ng_btsocket_rfcomm_untimeout(pcb);
790 switch (pcb->state) {
791 case NG_BTSOCKET_RFCOMM_DLC_CONFIGURING: /* XXX can we get here? */
792 case NG_BTSOCKET_RFCOMM_DLC_CONNECTING: /* XXX can we get here? */
793 case NG_BTSOCKET_RFCOMM_DLC_CONNECTED:
796 * Just change DLC state and enqueue RFCOMM task. It will
797 * queue and send DISC on the DLC.
800 pcb->state = NG_BTSOCKET_RFCOMM_DLC_DISCONNECTING;
801 soisdisconnecting(so);
803 ng_btsocket_rfcomm_task_wakeup();
806 case NG_BTSOCKET_RFCOMM_DLC_CLOSED:
807 case NG_BTSOCKET_RFCOMM_DLC_W4_CONNECT:
811 panic("%s: Invalid DLC state=%d, flags=%#x\n",
812 __func__, pcb->state, pcb->flags);
816 mtx_unlock(&pcb->pcb_mtx);
819 } /* ng_btsocket_rfcomm_disconnect */
822 * Listen on socket. First call to listen() will create listening RFCOMM session
826 ng_btsocket_rfcomm_listen(struct socket *so, int backlog, struct thread *td)
828 ng_btsocket_rfcomm_pcb_p pcb = so2rfcomm_pcb(so), pcb1;
829 ng_btsocket_rfcomm_session_p s = NULL;
830 struct socket *l2so = NULL;
831 int error, socreate_error, usedchannels;
835 if (pcb->channel > 30)
836 return (EADDRNOTAVAIL);
840 mtx_lock(&pcb->pcb_mtx);
842 if (pcb->channel == 0) {
843 mtx_lock(&ng_btsocket_rfcomm_sockets_mtx);
845 LIST_FOREACH(pcb1, &ng_btsocket_rfcomm_sockets, next)
846 if (pcb1->channel != 0 &&
847 bcmp(&pcb1->src, &pcb->src, sizeof(pcb->src)) == 0)
848 usedchannels |= (1 << (pcb1->channel - 1));
850 for (pcb->channel = 30; pcb->channel > 0; pcb->channel --)
851 if (!(usedchannels & (1 << (pcb->channel - 1))))
854 if (pcb->channel == 0) {
855 mtx_unlock(&ng_btsocket_rfcomm_sockets_mtx);
856 mtx_unlock(&pcb->pcb_mtx);
858 return (EADDRNOTAVAIL);
861 mtx_unlock(&ng_btsocket_rfcomm_sockets_mtx);
864 mtx_unlock(&pcb->pcb_mtx);
867 * Note that we will not check for errors in socreate() because
868 * if we failed to create L2CAP socket at this point we still
869 * might have already open session.
872 socreate_error = socreate(PF_BLUETOOTH, &l2so, SOCK_SEQPACKET,
873 BLUETOOTH_PROTO_L2CAP, td->td_ucred, td);
876 * Transition the socket and session into the LISTENING state. Check
877 * for collisions first, as there can only be one.
879 mtx_lock(&ng_btsocket_rfcomm_sessions_mtx);
881 error = solisten_proto_check(so);
886 LIST_FOREACH(s, &ng_btsocket_rfcomm_sessions, next)
887 if (s->state == NG_BTSOCKET_RFCOMM_SESSION_LISTENING)
892 * We need to create default RFCOMM session. Check if we have
893 * L2CAP socket. If l2so == NULL then error has the error code
897 error = socreate_error;
902 * Create default listen RFCOMM session. The default RFCOMM
903 * session will listen on ANY address.
905 * XXX FIXME Note that currently there is no way to adjust MTU
906 * for the default session.
908 error = ng_btsocket_rfcomm_session_create(&s, l2so,
909 NG_HCI_BDADDR_ANY, NULL, td);
915 solisten_proto(so, backlog);
918 mtx_unlock(&ng_btsocket_rfcomm_sessions_mtx);
920 * If we still have an l2so reference here, it's unneeded, so release
926 } /* ng_btsocket_listen */
933 ng_btsocket_rfcomm_peeraddr(struct socket *so, struct sockaddr **nam)
935 ng_btsocket_rfcomm_pcb_p pcb = so2rfcomm_pcb(so);
936 struct sockaddr_rfcomm sa;
941 bcopy(&pcb->dst, &sa.rfcomm_bdaddr, sizeof(sa.rfcomm_bdaddr));
942 sa.rfcomm_channel = pcb->channel;
943 sa.rfcomm_len = sizeof(sa);
944 sa.rfcomm_family = AF_BLUETOOTH;
946 *nam = sodupsockaddr((struct sockaddr *) &sa, M_NOWAIT);
948 return ((*nam == NULL)? ENOMEM : 0);
949 } /* ng_btsocket_rfcomm_peeraddr */
952 * Send data to socket
956 ng_btsocket_rfcomm_send(struct socket *so, int flags, struct mbuf *m,
957 struct sockaddr *nam, struct mbuf *control, struct thread *td)
959 ng_btsocket_rfcomm_pcb_t *pcb = so2rfcomm_pcb(so);
962 /* Check socket and input */
963 if (pcb == NULL || m == NULL || control != NULL) {
968 mtx_lock(&pcb->pcb_mtx);
970 /* Make sure DLC is connected */
971 if (pcb->state != NG_BTSOCKET_RFCOMM_DLC_CONNECTED) {
972 mtx_unlock(&pcb->pcb_mtx);
977 /* Put the packet on the socket's send queue and wakeup RFCOMM task */
978 sbappend(&pcb->so->so_snd, m, flags);
981 if (!(pcb->flags & NG_BTSOCKET_RFCOMM_DLC_SENDING)) {
982 pcb->flags |= NG_BTSOCKET_RFCOMM_DLC_SENDING;
983 error = ng_btsocket_rfcomm_task_wakeup();
986 mtx_unlock(&pcb->pcb_mtx);
988 NG_FREE_M(m); /* checks for != NULL */
992 } /* ng_btsocket_rfcomm_send */
999 ng_btsocket_rfcomm_sockaddr(struct socket *so, struct sockaddr **nam)
1001 ng_btsocket_rfcomm_pcb_p pcb = so2rfcomm_pcb(so);
1002 struct sockaddr_rfcomm sa;
1007 bcopy(&pcb->src, &sa.rfcomm_bdaddr, sizeof(sa.rfcomm_bdaddr));
1008 sa.rfcomm_channel = pcb->channel;
1009 sa.rfcomm_len = sizeof(sa);
1010 sa.rfcomm_family = AF_BLUETOOTH;
1012 *nam = sodupsockaddr((struct sockaddr *) &sa, M_NOWAIT);
1014 return ((*nam == NULL)? ENOMEM : 0);
1015 } /* ng_btsocket_rfcomm_sockaddr */
1018 * Upcall function for L2CAP sockets. Enqueue RFCOMM task.
1022 ng_btsocket_rfcomm_upcall(struct socket *so, void *arg, int waitflag)
1027 panic("%s: so == NULL\n", __func__);
1029 if ((error = ng_btsocket_rfcomm_task_wakeup()) != 0)
1030 NG_BTSOCKET_RFCOMM_ALERT(
1031 "%s: Could not enqueue RFCOMM task, error=%d\n", __func__, error);
1033 } /* ng_btsocket_rfcomm_upcall */
1036 * RFCOMM task. Will handle all RFCOMM sessions in one pass.
1037 * XXX FIXME does not scale very well
1041 ng_btsocket_rfcomm_sessions_task(void *ctx, int pending)
1043 ng_btsocket_rfcomm_session_p s = NULL, s_next = NULL;
1045 mtx_lock(&ng_btsocket_rfcomm_sessions_mtx);
1047 for (s = LIST_FIRST(&ng_btsocket_rfcomm_sessions); s != NULL; ) {
1048 mtx_lock(&s->session_mtx);
1049 s_next = LIST_NEXT(s, next);
1051 ng_btsocket_rfcomm_session_task(s);
1053 if (s->state == NG_BTSOCKET_RFCOMM_SESSION_CLOSED) {
1054 /* Unlink and clean the session */
1055 LIST_REMOVE(s, next);
1057 NG_BT_MBUFQ_DRAIN(&s->outq);
1058 if (!LIST_EMPTY(&s->dlcs))
1059 panic("%s: DLC list is not empty\n", __func__);
1061 /* Close L2CAP socket */
1062 SOCKBUF_LOCK(&s->l2so->so_rcv);
1063 soupcall_clear(s->l2so, SO_RCV);
1064 SOCKBUF_UNLOCK(&s->l2so->so_rcv);
1065 SOCKBUF_LOCK(&s->l2so->so_snd);
1066 soupcall_clear(s->l2so, SO_SND);
1067 SOCKBUF_UNLOCK(&s->l2so->so_snd);
1070 mtx_unlock(&s->session_mtx);
1072 mtx_destroy(&s->session_mtx);
1073 bzero(s, sizeof(*s));
1074 free(s, M_NETGRAPH_BTSOCKET_RFCOMM);
1076 mtx_unlock(&s->session_mtx);
1081 mtx_unlock(&ng_btsocket_rfcomm_sessions_mtx);
1082 } /* ng_btsocket_rfcomm_sessions_task */
1085 * Process RFCOMM session. Will handle all RFCOMM sockets in one pass.
1089 ng_btsocket_rfcomm_session_task(ng_btsocket_rfcomm_session_p s)
1091 mtx_assert(&s->session_mtx, MA_OWNED);
1093 if (s->l2so->so_rcv.sb_state & SBS_CANTRCVMORE) {
1094 NG_BTSOCKET_RFCOMM_INFO(
1095 "%s: L2CAP connection has been terminated, so=%p, so_state=%#x, so_count=%d, " \
1096 "state=%d, flags=%#x\n", __func__, s->l2so, s->l2so->so_state,
1097 s->l2so->so_count, s->state, s->flags);
1099 s->state = NG_BTSOCKET_RFCOMM_SESSION_CLOSED;
1100 ng_btsocket_rfcomm_session_clean(s);
1103 /* Now process upcall */
1105 /* Try to accept new L2CAP connection(s) */
1106 case NG_BTSOCKET_RFCOMM_SESSION_LISTENING:
1107 while (ng_btsocket_rfcomm_session_accept(s) == 0)
1111 /* Process the results of the L2CAP connect */
1112 case NG_BTSOCKET_RFCOMM_SESSION_CONNECTING:
1113 ng_btsocket_rfcomm_session_process_pcb(s);
1115 if (ng_btsocket_rfcomm_session_connect(s) != 0) {
1116 s->state = NG_BTSOCKET_RFCOMM_SESSION_CLOSED;
1117 ng_btsocket_rfcomm_session_clean(s);
1121 /* Try to receive/send more data */
1122 case NG_BTSOCKET_RFCOMM_SESSION_CONNECTED:
1123 case NG_BTSOCKET_RFCOMM_SESSION_OPEN:
1124 case NG_BTSOCKET_RFCOMM_SESSION_DISCONNECTING:
1125 ng_btsocket_rfcomm_session_process_pcb(s);
1127 if (ng_btsocket_rfcomm_session_receive(s) != 0) {
1128 s->state = NG_BTSOCKET_RFCOMM_SESSION_CLOSED;
1129 ng_btsocket_rfcomm_session_clean(s);
1130 } else if (ng_btsocket_rfcomm_session_send(s) != 0) {
1131 s->state = NG_BTSOCKET_RFCOMM_SESSION_CLOSED;
1132 ng_btsocket_rfcomm_session_clean(s);
1136 case NG_BTSOCKET_RFCOMM_SESSION_CLOSED:
1140 panic("%s: Invalid session state=%d, flags=%#x\n",
1141 __func__, s->state, s->flags);
1144 } /* ng_btsocket_rfcomm_session_task */
1147 * Process RFCOMM connection indicator. Caller must hold s->session_mtx
1150 static ng_btsocket_rfcomm_pcb_p
1151 ng_btsocket_rfcomm_connect_ind(ng_btsocket_rfcomm_session_p s, int channel)
1153 ng_btsocket_rfcomm_pcb_p pcb = NULL, pcb1 = NULL;
1154 ng_btsocket_l2cap_pcb_p l2pcb = NULL;
1157 mtx_assert(&s->session_mtx, MA_OWNED);
1160 * Try to find RFCOMM socket that listens on given source address
1161 * and channel. This will return the best possible match.
1164 l2pcb = so2l2cap_pcb(s->l2so);
1165 pcb = ng_btsocket_rfcomm_pcb_listener(&l2pcb->src, channel);
1170 * Check the pending connections queue and if we have space then
1171 * create new socket and set proper source and destination address,
1175 mtx_lock(&pcb->pcb_mtx);
1177 CURVNET_SET(pcb->so->so_vnet);
1178 so1 = sonewconn(pcb->so, 0);
1181 mtx_unlock(&pcb->pcb_mtx);
1187 * If we got here than we have created new socket. So complete the
1188 * connection. Set source and destination address from the session.
1191 pcb1 = so2rfcomm_pcb(so1);
1193 panic("%s: pcb1 == NULL\n", __func__);
1195 mtx_lock(&pcb1->pcb_mtx);
1197 bcopy(&l2pcb->src, &pcb1->src, sizeof(pcb1->src));
1198 bcopy(&l2pcb->dst, &pcb1->dst, sizeof(pcb1->dst));
1199 pcb1->channel = channel;
1201 /* Link new DLC to the session. We already hold s->session_mtx */
1202 LIST_INSERT_HEAD(&s->dlcs, pcb1, session_next);
1205 mtx_unlock(&pcb1->pcb_mtx);
1208 } /* ng_btsocket_rfcomm_connect_ind */
1211 * Process RFCOMM connect confirmation. Caller must hold s->session_mtx.
1215 ng_btsocket_rfcomm_connect_cfm(ng_btsocket_rfcomm_session_p s)
1217 ng_btsocket_rfcomm_pcb_p pcb = NULL, pcb_next = NULL;
1220 mtx_assert(&s->session_mtx, MA_OWNED);
1223 * Wake up all waiting sockets and send PN request for each of them.
1224 * Note that timeout already been set in ng_btsocket_rfcomm_connect()
1226 * Note: cannot use LIST_FOREACH because ng_btsocket_rfcomm_pcb_kill
1227 * will unlink DLC from the session
1230 for (pcb = LIST_FIRST(&s->dlcs); pcb != NULL; ) {
1231 mtx_lock(&pcb->pcb_mtx);
1232 pcb_next = LIST_NEXT(pcb, session_next);
1234 if (pcb->state == NG_BTSOCKET_RFCOMM_DLC_W4_CONNECT) {
1236 bcopy(&so2l2cap_pcb(s->l2so)->src, &pcb->src,
1239 error = ng_btsocket_rfcomm_send_pn(pcb);
1241 pcb->state = NG_BTSOCKET_RFCOMM_DLC_CONFIGURING;
1243 ng_btsocket_rfcomm_pcb_kill(pcb, error);
1246 mtx_unlock(&pcb->pcb_mtx);
1249 } /* ng_btsocket_rfcomm_connect_cfm */
1251 /*****************************************************************************
1252 *****************************************************************************
1254 *****************************************************************************
1255 *****************************************************************************/
1258 * Create new RFCOMM session. That function WILL NOT take ownership over l2so.
1259 * Caller MUST free l2so if function failed.
1263 ng_btsocket_rfcomm_session_create(ng_btsocket_rfcomm_session_p *sp,
1264 struct socket *l2so, bdaddr_p src, bdaddr_p dst,
1267 ng_btsocket_rfcomm_session_p s = NULL;
1268 struct sockaddr_l2cap l2sa;
1269 struct sockopt l2sopt;
1273 mtx_assert(&ng_btsocket_rfcomm_sessions_mtx, MA_OWNED);
1275 /* Allocate the RFCOMM session */
1276 s = malloc(sizeof(*s),
1277 M_NETGRAPH_BTSOCKET_RFCOMM, M_NOWAIT | M_ZERO);
1282 s->mtu = RFCOMM_DEFAULT_MTU;
1284 s->state = NG_BTSOCKET_RFCOMM_SESSION_CLOSED;
1285 NG_BT_MBUFQ_INIT(&s->outq, ifqmaxlen);
1288 * XXX Mark session mutex as DUPOK to prevent "duplicated lock of
1289 * the same type" message. When accepting new L2CAP connection
1290 * ng_btsocket_rfcomm_session_accept() holds both session mutexes
1291 * for "old" (accepting) session and "new" (created) session.
1294 mtx_init(&s->session_mtx, "btsocks_rfcomm_session_mtx", NULL,
1297 LIST_INIT(&s->dlcs);
1299 /* Prepare L2CAP socket */
1300 SOCKBUF_LOCK(&l2so->so_rcv);
1301 soupcall_set(l2so, SO_RCV, ng_btsocket_rfcomm_upcall, NULL);
1302 SOCKBUF_UNLOCK(&l2so->so_rcv);
1303 SOCKBUF_LOCK(&l2so->so_snd);
1304 soupcall_set(l2so, SO_SND, ng_btsocket_rfcomm_upcall, NULL);
1305 SOCKBUF_UNLOCK(&l2so->so_snd);
1306 l2so->so_state |= SS_NBIO;
1309 mtx_lock(&s->session_mtx);
1312 * "src" == NULL and "dst" == NULL means just create session.
1313 * caller must do the rest
1316 if (src == NULL && dst == NULL)
1320 * Set incoming MTU on L2CAP socket. It is RFCOMM session default MTU
1321 * plus 5 bytes: RFCOMM frame header, one extra byte for length and one
1322 * extra byte for credits.
1325 mtu = s->mtu + sizeof(struct rfcomm_frame_hdr) + 1 + 1;
1327 l2sopt.sopt_dir = SOPT_SET;
1328 l2sopt.sopt_level = SOL_L2CAP;
1329 l2sopt.sopt_name = SO_L2CAP_IMTU;
1330 l2sopt.sopt_val = (void *) &mtu;
1331 l2sopt.sopt_valsize = sizeof(mtu);
1332 l2sopt.sopt_td = NULL;
1334 error = sosetopt(s->l2so, &l2sopt);
1338 /* Bind socket to "src" address */
1339 l2sa.l2cap_len = sizeof(l2sa);
1340 l2sa.l2cap_family = AF_BLUETOOTH;
1341 l2sa.l2cap_psm = (dst == NULL)? htole16(NG_L2CAP_PSM_RFCOMM) : 0;
1342 bcopy(src, &l2sa.l2cap_bdaddr, sizeof(l2sa.l2cap_bdaddr));
1344 l2sa.l2cap_bdaddr_type = BDADDR_BREDR;
1346 error = sobind(s->l2so, (struct sockaddr *) &l2sa, td);
1350 /* If "dst" is not NULL then initiate connect(), otherwise listen() */
1353 s->state = NG_BTSOCKET_RFCOMM_SESSION_LISTENING;
1355 error = solisten(s->l2so, 10, td);
1359 s->flags = NG_BTSOCKET_RFCOMM_SESSION_INITIATOR;
1360 s->state = NG_BTSOCKET_RFCOMM_SESSION_CONNECTING;
1362 l2sa.l2cap_len = sizeof(l2sa);
1363 l2sa.l2cap_family = AF_BLUETOOTH;
1364 l2sa.l2cap_psm = htole16(NG_L2CAP_PSM_RFCOMM);
1365 bcopy(dst, &l2sa.l2cap_bdaddr, sizeof(l2sa.l2cap_bdaddr));
1367 l2sa.l2cap_bdaddr_type = BDADDR_BREDR;
1369 error = soconnect(s->l2so, (struct sockaddr *) &l2sa, td);
1375 LIST_INSERT_HEAD(&ng_btsocket_rfcomm_sessions, s, next);
1378 mtx_unlock(&s->session_mtx);
1383 mtx_unlock(&s->session_mtx);
1385 /* Return L2CAP socket back to its original state */
1386 SOCKBUF_LOCK(&l2so->so_rcv);
1387 soupcall_clear(s->l2so, SO_RCV);
1388 SOCKBUF_UNLOCK(&l2so->so_rcv);
1389 SOCKBUF_LOCK(&l2so->so_snd);
1390 soupcall_clear(s->l2so, SO_SND);
1391 SOCKBUF_UNLOCK(&l2so->so_snd);
1392 l2so->so_state &= ~SS_NBIO;
1394 mtx_destroy(&s->session_mtx);
1395 bzero(s, sizeof(*s));
1396 free(s, M_NETGRAPH_BTSOCKET_RFCOMM);
1399 } /* ng_btsocket_rfcomm_session_create */
1402 * Process accept() on RFCOMM session
1403 * XXX FIXME locking for "l2so"?
1407 ng_btsocket_rfcomm_session_accept(ng_btsocket_rfcomm_session_p s0)
1409 struct socket *l2so;
1410 struct sockaddr_l2cap *l2sa = NULL;
1411 ng_btsocket_l2cap_pcb_t *l2pcb = NULL;
1412 ng_btsocket_rfcomm_session_p s = NULL;
1415 mtx_assert(&ng_btsocket_rfcomm_sessions_mtx, MA_OWNED);
1416 mtx_assert(&s0->session_mtx, MA_OWNED);
1418 SOLISTEN_LOCK(s0->l2so);
1419 error = solisten_dequeue(s0->l2so, &l2so, 0);
1420 if (error == EWOULDBLOCK)
1423 NG_BTSOCKET_RFCOMM_ERR(
1424 "%s: Could not accept connection on L2CAP socket, error=%d\n", __func__, error);
1428 error = soaccept(l2so, (struct sockaddr **) &l2sa);
1430 NG_BTSOCKET_RFCOMM_ERR(
1431 "%s: soaccept() on L2CAP socket failed, error=%d\n", __func__, error);
1438 * Check if there is already active RFCOMM session between two devices.
1439 * If so then close L2CAP connection. We only support one RFCOMM session
1440 * between each pair of devices. Note that here we assume session in any
1441 * state. The session even could be in the middle of disconnecting.
1444 l2pcb = so2l2cap_pcb(l2so);
1445 s = ng_btsocket_rfcomm_session_by_addr(&l2pcb->src, &l2pcb->dst);
1447 /* Create a new RFCOMM session */
1448 error = ng_btsocket_rfcomm_session_create(&s, l2so, NULL, NULL,
1449 curthread /* XXX */);
1451 mtx_lock(&s->session_mtx);
1454 s->state = NG_BTSOCKET_RFCOMM_SESSION_CONNECTED;
1457 * Adjust MTU on incoming connection. Reserve 5 bytes:
1458 * RFCOMM frame header, one extra byte for length and
1459 * one extra byte for credits.
1462 s->mtu = min(l2pcb->imtu, l2pcb->omtu) -
1463 sizeof(struct rfcomm_frame_hdr) - 1 - 1;
1465 mtx_unlock(&s->session_mtx);
1467 NG_BTSOCKET_RFCOMM_ALERT(
1468 "%s: Failed to create new RFCOMM session, error=%d\n", __func__, error);
1473 NG_BTSOCKET_RFCOMM_WARN(
1474 "%s: Rejecting duplicating RFCOMM session between src=%x:%x:%x:%x:%x:%x and " \
1475 "dst=%x:%x:%x:%x:%x:%x, state=%d, flags=%#x\n", __func__,
1476 l2pcb->src.b[5], l2pcb->src.b[4], l2pcb->src.b[3],
1477 l2pcb->src.b[2], l2pcb->src.b[1], l2pcb->src.b[0],
1478 l2pcb->dst.b[5], l2pcb->dst.b[4], l2pcb->dst.b[3],
1479 l2pcb->dst.b[2], l2pcb->dst.b[1], l2pcb->dst.b[0],
1480 s->state, s->flags);
1487 } /* ng_btsocket_rfcomm_session_accept */
1490 * Process connect() on RFCOMM session
1491 * XXX FIXME locking for "l2so"?
1495 ng_btsocket_rfcomm_session_connect(ng_btsocket_rfcomm_session_p s)
1497 ng_btsocket_l2cap_pcb_p l2pcb = so2l2cap_pcb(s->l2so);
1500 mtx_assert(&s->session_mtx, MA_OWNED);
1502 /* First check if connection has failed */
1503 if ((error = s->l2so->so_error) != 0) {
1504 s->l2so->so_error = 0;
1506 NG_BTSOCKET_RFCOMM_ERR(
1507 "%s: Could not connect RFCOMM session, error=%d, state=%d, flags=%#x\n",
1508 __func__, error, s->state, s->flags);
1513 /* Is connection still in progress? */
1514 if (s->l2so->so_state & SS_ISCONNECTING)
1518 * If we got here then we are connected. Send SABM on DLCI 0 to
1519 * open multiplexor channel.
1523 s->state = NG_BTSOCKET_RFCOMM_SESSION_CONNECTED;
1526 * Adjust MTU on outgoing connection. Reserve 5 bytes: RFCOMM
1527 * frame header, one extra byte for length and one extra byte
1531 s->mtu = min(l2pcb->imtu, l2pcb->omtu) -
1532 sizeof(struct rfcomm_frame_hdr) - 1 - 1;
1534 error = ng_btsocket_rfcomm_send_command(s,RFCOMM_FRAME_SABM,0);
1536 error = ng_btsocket_rfcomm_task_wakeup();
1540 }/* ng_btsocket_rfcomm_session_connect */
1543 * Receive data on RFCOMM session
1544 * XXX FIXME locking for "l2so"?
1548 ng_btsocket_rfcomm_session_receive(ng_btsocket_rfcomm_session_p s)
1550 struct mbuf *m = NULL;
1552 int more, flags, error;
1554 mtx_assert(&s->session_mtx, MA_OWNED);
1556 /* Can we read from the L2CAP socket? */
1557 if (!soreadable(s->l2so))
1560 /* First check for error on L2CAP socket */
1561 if ((error = s->l2so->so_error) != 0) {
1562 s->l2so->so_error = 0;
1564 NG_BTSOCKET_RFCOMM_ERR(
1565 "%s: Could not receive data from L2CAP socket, error=%d, state=%d, flags=%#x\n",
1566 __func__, error, s->state, s->flags);
1572 * Read all packets from the L2CAP socket.
1573 * XXX FIXME/VERIFY is that correct? For now use m->m_nextpkt as
1574 * indication that there is more packets on the socket's buffer.
1575 * Also what should we use in uio.uio_resid?
1576 * May be s->mtu + sizeof(struct rfcomm_frame_hdr) + 1 + 1?
1579 for (more = 1; more; ) {
1580 /* Try to get next packet from socket */
1581 bzero(&uio, sizeof(uio));
1582 /* uio.uio_td = NULL; */
1583 uio.uio_resid = 1000000000;
1584 flags = MSG_DONTWAIT;
1587 error = soreceive(s->l2so, NULL, &uio, &m,
1588 (struct mbuf **) NULL, &flags);
1590 if (error == EWOULDBLOCK)
1591 return (0); /* XXX can happen? */
1593 NG_BTSOCKET_RFCOMM_ERR(
1594 "%s: Could not receive data from L2CAP socket, error=%d\n", __func__, error);
1599 more = (m->m_nextpkt != NULL);
1600 m->m_nextpkt = NULL;
1602 ng_btsocket_rfcomm_receive_frame(s, m);
1606 } /* ng_btsocket_rfcomm_session_receive */
1609 * Send data on RFCOMM session
1610 * XXX FIXME locking for "l2so"?
1614 ng_btsocket_rfcomm_session_send(ng_btsocket_rfcomm_session_p s)
1616 struct mbuf *m = NULL;
1619 mtx_assert(&s->session_mtx, MA_OWNED);
1621 /* Send as much as we can from the session queue */
1622 while (sowriteable(s->l2so)) {
1623 /* Check if socket still OK */
1624 if ((error = s->l2so->so_error) != 0) {
1625 s->l2so->so_error = 0;
1627 NG_BTSOCKET_RFCOMM_ERR(
1628 "%s: Detected error=%d on L2CAP socket, state=%d, flags=%#x\n",
1629 __func__, error, s->state, s->flags);
1634 NG_BT_MBUFQ_DEQUEUE(&s->outq, m);
1636 return (0); /* we are done */
1638 /* Call send function on the L2CAP socket */
1639 error = (*s->l2so->so_proto->pr_usrreqs->pru_send)(s->l2so,
1640 0, m, NULL, NULL, curthread /* XXX */);
1642 NG_BTSOCKET_RFCOMM_ERR(
1643 "%s: Could not send data to L2CAP socket, error=%d\n", __func__, error);
1650 } /* ng_btsocket_rfcomm_session_send */
1653 * Close and disconnect all DLCs for the given session. Caller must hold
1654 * s->sesson_mtx. Will wakeup session.
1658 ng_btsocket_rfcomm_session_clean(ng_btsocket_rfcomm_session_p s)
1660 ng_btsocket_rfcomm_pcb_p pcb = NULL, pcb_next = NULL;
1663 mtx_assert(&s->session_mtx, MA_OWNED);
1666 * Note: cannot use LIST_FOREACH because ng_btsocket_rfcomm_pcb_kill
1667 * will unlink DLC from the session
1670 for (pcb = LIST_FIRST(&s->dlcs); pcb != NULL; ) {
1671 mtx_lock(&pcb->pcb_mtx);
1672 pcb_next = LIST_NEXT(pcb, session_next);
1674 NG_BTSOCKET_RFCOMM_INFO(
1675 "%s: Disconnecting dlci=%d, state=%d, flags=%#x\n",
1676 __func__, pcb->dlci, pcb->state, pcb->flags);
1678 if (pcb->state == NG_BTSOCKET_RFCOMM_DLC_CONNECTED)
1681 error = ECONNREFUSED;
1683 ng_btsocket_rfcomm_pcb_kill(pcb, error);
1685 mtx_unlock(&pcb->pcb_mtx);
1688 } /* ng_btsocket_rfcomm_session_clean */
1691 * Process all DLCs on the session. Caller MUST hold s->session_mtx.
1695 ng_btsocket_rfcomm_session_process_pcb(ng_btsocket_rfcomm_session_p s)
1697 ng_btsocket_rfcomm_pcb_p pcb = NULL, pcb_next = NULL;
1700 mtx_assert(&s->session_mtx, MA_OWNED);
1703 * Note: cannot use LIST_FOREACH because ng_btsocket_rfcomm_pcb_kill
1704 * will unlink DLC from the session
1707 for (pcb = LIST_FIRST(&s->dlcs); pcb != NULL; ) {
1708 mtx_lock(&pcb->pcb_mtx);
1709 pcb_next = LIST_NEXT(pcb, session_next);
1711 switch (pcb->state) {
1713 * If DLC in W4_CONNECT state then we should check for both
1714 * timeout and detach.
1717 case NG_BTSOCKET_RFCOMM_DLC_W4_CONNECT:
1718 if (pcb->flags & NG_BTSOCKET_RFCOMM_DLC_DETACHED)
1719 ng_btsocket_rfcomm_pcb_kill(pcb, 0);
1720 else if (pcb->flags & NG_BTSOCKET_RFCOMM_DLC_TIMEDOUT)
1721 ng_btsocket_rfcomm_pcb_kill(pcb, ETIMEDOUT);
1725 * If DLC in CONFIGURING or CONNECTING state then we only
1726 * should check for timeout. If detach() was called then
1727 * DLC will be moved into DISCONNECTING state.
1730 case NG_BTSOCKET_RFCOMM_DLC_CONFIGURING:
1731 case NG_BTSOCKET_RFCOMM_DLC_CONNECTING:
1732 if (pcb->flags & NG_BTSOCKET_RFCOMM_DLC_TIMEDOUT)
1733 ng_btsocket_rfcomm_pcb_kill(pcb, ETIMEDOUT);
1737 * If DLC in CONNECTED state then we need to send data (if any)
1738 * from the socket's send queue. Note that we will send data
1739 * from either all sockets or none. This may overload session's
1740 * outgoing queue (but we do not check for that).
1742 * XXX FIXME need scheduler for RFCOMM sockets
1745 case NG_BTSOCKET_RFCOMM_DLC_CONNECTED:
1746 error = ng_btsocket_rfcomm_pcb_send(pcb, ALOT);
1748 ng_btsocket_rfcomm_pcb_kill(pcb, error);
1752 * If DLC in DISCONNECTING state then we must send DISC frame.
1753 * Note that if DLC has timeout set then we do not need to
1754 * resend DISC frame.
1756 * XXX FIXME need to drain all data from the socket's queue
1757 * if LINGER option was set
1760 case NG_BTSOCKET_RFCOMM_DLC_DISCONNECTING:
1761 if (!(pcb->flags & NG_BTSOCKET_RFCOMM_DLC_TIMO)) {
1762 error = ng_btsocket_rfcomm_send_command(
1763 pcb->session, RFCOMM_FRAME_DISC,
1766 ng_btsocket_rfcomm_timeout(pcb);
1768 ng_btsocket_rfcomm_pcb_kill(pcb, error);
1769 } else if (pcb->flags & NG_BTSOCKET_RFCOMM_DLC_TIMEDOUT)
1770 ng_btsocket_rfcomm_pcb_kill(pcb, ETIMEDOUT);
1773 /* case NG_BTSOCKET_RFCOMM_DLC_CLOSED: */
1775 panic("%s: Invalid DLC state=%d, flags=%#x\n",
1776 __func__, pcb->state, pcb->flags);
1780 mtx_unlock(&pcb->pcb_mtx);
1783 } /* ng_btsocket_rfcomm_session_process_pcb */
1786 * Find RFCOMM session between "src" and "dst".
1787 * Caller MUST hold ng_btsocket_rfcomm_sessions_mtx.
1790 static ng_btsocket_rfcomm_session_p
1791 ng_btsocket_rfcomm_session_by_addr(bdaddr_p src, bdaddr_p dst)
1793 ng_btsocket_rfcomm_session_p s = NULL;
1794 ng_btsocket_l2cap_pcb_p l2pcb = NULL;
1797 mtx_assert(&ng_btsocket_rfcomm_sessions_mtx, MA_OWNED);
1799 any_src = (bcmp(src, NG_HCI_BDADDR_ANY, sizeof(*src)) == 0);
1801 LIST_FOREACH(s, &ng_btsocket_rfcomm_sessions, next) {
1802 l2pcb = so2l2cap_pcb(s->l2so);
1804 if ((any_src || bcmp(&l2pcb->src, src, sizeof(*src)) == 0) &&
1805 bcmp(&l2pcb->dst, dst, sizeof(*dst)) == 0)
1810 } /* ng_btsocket_rfcomm_session_by_addr */
1812 /*****************************************************************************
1813 *****************************************************************************
1815 *****************************************************************************
1816 *****************************************************************************/
1819 * Process incoming RFCOMM frame. Caller must hold s->session_mtx.
1820 * XXX FIXME check frame length
1824 ng_btsocket_rfcomm_receive_frame(ng_btsocket_rfcomm_session_p s,
1827 struct rfcomm_frame_hdr *hdr = NULL;
1828 struct mbuf *m = NULL;
1830 u_int8_t dlci, type;
1833 mtx_assert(&s->session_mtx, MA_OWNED);
1835 /* Pullup as much as we can into first mbuf (for direct access) */
1836 length = min(m0->m_pkthdr.len, MHLEN);
1837 if (m0->m_len < length) {
1838 if ((m0 = m_pullup(m0, length)) == NULL) {
1839 NG_BTSOCKET_RFCOMM_ALERT(
1840 "%s: m_pullup(%d) failed\n", __func__, length);
1846 hdr = mtod(m0, struct rfcomm_frame_hdr *);
1847 dlci = RFCOMM_DLCI(hdr->address);
1848 type = RFCOMM_TYPE(hdr->control);
1850 /* Test EA bit in length. If not set then we have 2 bytes of length */
1851 if (!RFCOMM_EA(hdr->length)) {
1852 bcopy(&hdr->length, &length, sizeof(length));
1853 length = le16toh(length) >> 1;
1854 m_adj(m0, sizeof(*hdr) + 1);
1856 length = hdr->length >> 1;
1857 m_adj(m0, sizeof(*hdr));
1860 NG_BTSOCKET_RFCOMM_INFO(
1861 "%s: Got frame type=%#x, dlci=%d, length=%d, cr=%d, pf=%d, len=%d\n",
1862 __func__, type, dlci, length, RFCOMM_CR(hdr->address),
1863 RFCOMM_PF(hdr->control), m0->m_pkthdr.len);
1866 * Get FCS (the last byte in the frame)
1867 * XXX this will not work if mbuf chain ends with empty mbuf.
1868 * XXX let's hope it never happens :)
1871 for (m = m0; m->m_next != NULL; m = m->m_next)
1874 panic("%s: Empty mbuf at the end of the chain, len=%d\n",
1875 __func__, m->m_len);
1878 * Check FCS. We only need to calculate FCS on first 2 or 3 bytes
1879 * and already m_pullup'ed mbuf chain, so it should be safe.
1882 if (ng_btsocket_rfcomm_check_fcs((u_int8_t *) hdr, type, m->m_data[m->m_len - 1])) {
1883 NG_BTSOCKET_RFCOMM_ERR(
1884 "%s: Invalid RFCOMM packet. Bad checksum\n", __func__);
1890 m_adj(m0, -1); /* Trim FCS byte */
1893 * Process RFCOMM frame.
1895 * From TS 07.10 spec
1897 * "... In the case where a SABM or DISC command with the P bit set
1898 * to 0 is received then the received frame shall be discarded..."
1900 * "... If a unsolicited DM response is received then the frame shall
1901 * be processed irrespective of the P/F setting... "
1903 * "... The station may transmit response frames with the F bit set
1904 * to 0 at any opportunity on an asynchronous basis. However, in the
1905 * case where a UA response is received with the F bit set to 0 then
1906 * the received frame shall be discarded..."
1908 * From Bluetooth spec
1910 * "... When credit based flow control is being used, the meaning of
1911 * the P/F bit in the control field of the RFCOMM header is redefined
1912 * for UIH frames..."
1916 case RFCOMM_FRAME_SABM:
1917 if (RFCOMM_PF(hdr->control))
1918 error = ng_btsocket_rfcomm_receive_sabm(s, dlci);
1921 case RFCOMM_FRAME_DISC:
1922 if (RFCOMM_PF(hdr->control))
1923 error = ng_btsocket_rfcomm_receive_disc(s, dlci);
1926 case RFCOMM_FRAME_UA:
1927 if (RFCOMM_PF(hdr->control))
1928 error = ng_btsocket_rfcomm_receive_ua(s, dlci);
1931 case RFCOMM_FRAME_DM:
1932 error = ng_btsocket_rfcomm_receive_dm(s, dlci);
1935 case RFCOMM_FRAME_UIH:
1937 error = ng_btsocket_rfcomm_receive_mcc(s, m0);
1939 error = ng_btsocket_rfcomm_receive_uih(s, dlci,
1940 RFCOMM_PF(hdr->control), m0);
1946 NG_BTSOCKET_RFCOMM_ERR(
1947 "%s: Invalid RFCOMM packet. Unknown type=%#x\n", __func__, type);
1955 } /* ng_btsocket_rfcomm_receive_frame */
1958 * Process RFCOMM SABM frame
1962 ng_btsocket_rfcomm_receive_sabm(ng_btsocket_rfcomm_session_p s, int dlci)
1964 ng_btsocket_rfcomm_pcb_p pcb = NULL;
1967 mtx_assert(&s->session_mtx, MA_OWNED);
1969 NG_BTSOCKET_RFCOMM_INFO(
1970 "%s: Got SABM, session state=%d, flags=%#x, mtu=%d, dlci=%d\n",
1971 __func__, s->state, s->flags, s->mtu, dlci);
1973 /* DLCI == 0 means open multiplexor channel */
1976 case NG_BTSOCKET_RFCOMM_SESSION_CONNECTED:
1977 case NG_BTSOCKET_RFCOMM_SESSION_OPEN:
1978 error = ng_btsocket_rfcomm_send_command(s,
1979 RFCOMM_FRAME_UA, dlci);
1981 s->state = NG_BTSOCKET_RFCOMM_SESSION_OPEN;
1982 ng_btsocket_rfcomm_connect_cfm(s);
1984 s->state = NG_BTSOCKET_RFCOMM_SESSION_CLOSED;
1985 ng_btsocket_rfcomm_session_clean(s);
1990 NG_BTSOCKET_RFCOMM_WARN(
1991 "%s: Got SABM for session in invalid state state=%d, flags=%#x\n",
1992 __func__, s->state, s->flags);
2000 /* Make sure multiplexor channel is open */
2001 if (s->state != NG_BTSOCKET_RFCOMM_SESSION_OPEN) {
2002 NG_BTSOCKET_RFCOMM_ERR(
2003 "%s: Got SABM for dlci=%d with mulitplexor channel closed, state=%d, " \
2004 "flags=%#x\n", __func__, dlci, s->state, s->flags);
2010 * Check if we have this DLCI. This might happen when remote
2011 * peer uses PN command before actual open (SABM) happens.
2014 pcb = ng_btsocket_rfcomm_pcb_by_dlci(s, dlci);
2016 mtx_lock(&pcb->pcb_mtx);
2018 if (pcb->state != NG_BTSOCKET_RFCOMM_DLC_CONNECTING) {
2019 NG_BTSOCKET_RFCOMM_ERR(
2020 "%s: Got SABM for dlci=%d in invalid state=%d, flags=%#x\n",
2021 __func__, dlci, pcb->state, pcb->flags);
2022 mtx_unlock(&pcb->pcb_mtx);
2027 ng_btsocket_rfcomm_untimeout(pcb);
2029 error = ng_btsocket_rfcomm_send_command(s,RFCOMM_FRAME_UA,dlci);
2031 error = ng_btsocket_rfcomm_send_msc(pcb);
2034 pcb->state = NG_BTSOCKET_RFCOMM_DLC_CONNECTED;
2035 soisconnected(pcb->so);
2037 ng_btsocket_rfcomm_pcb_kill(pcb, error);
2039 mtx_unlock(&pcb->pcb_mtx);
2045 * We do not have requested DLCI, so it must be an incoming connection
2046 * with default parameters. Try to accept it.
2049 pcb = ng_btsocket_rfcomm_connect_ind(s, RFCOMM_SRVCHANNEL(dlci));
2051 mtx_lock(&pcb->pcb_mtx);
2055 error = ng_btsocket_rfcomm_send_command(s,RFCOMM_FRAME_UA,dlci);
2057 error = ng_btsocket_rfcomm_send_msc(pcb);
2060 pcb->state = NG_BTSOCKET_RFCOMM_DLC_CONNECTED;
2061 soisconnected(pcb->so);
2063 ng_btsocket_rfcomm_pcb_kill(pcb, error);
2065 mtx_unlock(&pcb->pcb_mtx);
2067 /* Nobody is listen()ing on the requested DLCI */
2068 error = ng_btsocket_rfcomm_send_command(s,RFCOMM_FRAME_DM,dlci);
2071 } /* ng_btsocket_rfcomm_receive_sabm */
2074 * Process RFCOMM DISC frame
2078 ng_btsocket_rfcomm_receive_disc(ng_btsocket_rfcomm_session_p s, int dlci)
2080 ng_btsocket_rfcomm_pcb_p pcb = NULL;
2083 mtx_assert(&s->session_mtx, MA_OWNED);
2085 NG_BTSOCKET_RFCOMM_INFO(
2086 "%s: Got DISC, session state=%d, flags=%#x, mtu=%d, dlci=%d\n",
2087 __func__, s->state, s->flags, s->mtu, dlci);
2089 /* DLCI == 0 means close multiplexor channel */
2091 /* XXX FIXME assume that remote side will close the socket */
2092 error = ng_btsocket_rfcomm_send_command(s, RFCOMM_FRAME_UA, 0);
2094 if (s->state == NG_BTSOCKET_RFCOMM_SESSION_DISCONNECTING)
2095 s->state = NG_BTSOCKET_RFCOMM_SESSION_CLOSED; /* XXX */
2097 s->state = NG_BTSOCKET_RFCOMM_SESSION_DISCONNECTING;
2099 s->state = NG_BTSOCKET_RFCOMM_SESSION_CLOSED; /* XXX */
2101 ng_btsocket_rfcomm_session_clean(s);
2103 pcb = ng_btsocket_rfcomm_pcb_by_dlci(s, dlci);
2107 mtx_lock(&pcb->pcb_mtx);
2109 NG_BTSOCKET_RFCOMM_INFO(
2110 "%s: Got DISC for dlci=%d, state=%d, flags=%#x\n",
2111 __func__, dlci, pcb->state, pcb->flags);
2113 error = ng_btsocket_rfcomm_send_command(s,
2114 RFCOMM_FRAME_UA, dlci);
2116 if (pcb->state == NG_BTSOCKET_RFCOMM_DLC_CONNECTED)
2121 ng_btsocket_rfcomm_pcb_kill(pcb, err);
2123 mtx_unlock(&pcb->pcb_mtx);
2125 NG_BTSOCKET_RFCOMM_WARN(
2126 "%s: Got DISC for non-existing dlci=%d\n", __func__, dlci);
2128 error = ng_btsocket_rfcomm_send_command(s,
2129 RFCOMM_FRAME_DM, dlci);
2134 } /* ng_btsocket_rfcomm_receive_disc */
2137 * Process RFCOMM UA frame
2141 ng_btsocket_rfcomm_receive_ua(ng_btsocket_rfcomm_session_p s, int dlci)
2143 ng_btsocket_rfcomm_pcb_p pcb = NULL;
2146 mtx_assert(&s->session_mtx, MA_OWNED);
2148 NG_BTSOCKET_RFCOMM_INFO(
2149 "%s: Got UA, session state=%d, flags=%#x, mtu=%d, dlci=%d\n",
2150 __func__, s->state, s->flags, s->mtu, dlci);
2152 /* dlci == 0 means multiplexor channel */
2155 case NG_BTSOCKET_RFCOMM_SESSION_CONNECTED:
2156 s->state = NG_BTSOCKET_RFCOMM_SESSION_OPEN;
2157 ng_btsocket_rfcomm_connect_cfm(s);
2160 case NG_BTSOCKET_RFCOMM_SESSION_DISCONNECTING:
2161 s->state = NG_BTSOCKET_RFCOMM_SESSION_CLOSED;
2162 ng_btsocket_rfcomm_session_clean(s);
2166 NG_BTSOCKET_RFCOMM_WARN(
2167 "%s: Got UA for session in invalid state=%d(%d), flags=%#x, mtu=%d\n",
2168 __func__, s->state, INITIATOR(s), s->flags,
2177 /* Check if we have this DLCI */
2178 pcb = ng_btsocket_rfcomm_pcb_by_dlci(s, dlci);
2180 mtx_lock(&pcb->pcb_mtx);
2182 NG_BTSOCKET_RFCOMM_INFO(
2183 "%s: Got UA for dlci=%d, state=%d, flags=%#x\n",
2184 __func__, dlci, pcb->state, pcb->flags);
2186 switch (pcb->state) {
2187 case NG_BTSOCKET_RFCOMM_DLC_CONNECTING:
2188 ng_btsocket_rfcomm_untimeout(pcb);
2190 error = ng_btsocket_rfcomm_send_msc(pcb);
2192 pcb->state = NG_BTSOCKET_RFCOMM_DLC_CONNECTED;
2193 soisconnected(pcb->so);
2197 case NG_BTSOCKET_RFCOMM_DLC_DISCONNECTING:
2198 ng_btsocket_rfcomm_pcb_kill(pcb, 0);
2202 NG_BTSOCKET_RFCOMM_WARN(
2203 "%s: Got UA for dlci=%d in invalid state=%d, flags=%#x\n",
2204 __func__, dlci, pcb->state, pcb->flags);
2209 mtx_unlock(&pcb->pcb_mtx);
2211 NG_BTSOCKET_RFCOMM_WARN(
2212 "%s: Got UA for non-existing dlci=%d\n", __func__, dlci);
2214 error = ng_btsocket_rfcomm_send_command(s,RFCOMM_FRAME_DM,dlci);
2218 } /* ng_btsocket_rfcomm_receive_ua */
2221 * Process RFCOMM DM frame
2225 ng_btsocket_rfcomm_receive_dm(ng_btsocket_rfcomm_session_p s, int dlci)
2227 ng_btsocket_rfcomm_pcb_p pcb = NULL;
2230 mtx_assert(&s->session_mtx, MA_OWNED);
2232 NG_BTSOCKET_RFCOMM_INFO(
2233 "%s: Got DM, session state=%d, flags=%#x, mtu=%d, dlci=%d\n",
2234 __func__, s->state, s->flags, s->mtu, dlci);
2236 /* DLCI == 0 means multiplexor channel */
2238 /* Disconnect all dlc's on the session */
2239 s->state = NG_BTSOCKET_RFCOMM_SESSION_CLOSED;
2240 ng_btsocket_rfcomm_session_clean(s);
2242 pcb = ng_btsocket_rfcomm_pcb_by_dlci(s, dlci);
2244 mtx_lock(&pcb->pcb_mtx);
2246 NG_BTSOCKET_RFCOMM_INFO(
2247 "%s: Got DM for dlci=%d, state=%d, flags=%#x\n",
2248 __func__, dlci, pcb->state, pcb->flags);
2250 if (pcb->state == NG_BTSOCKET_RFCOMM_DLC_CONNECTED)
2253 error = ECONNREFUSED;
2255 ng_btsocket_rfcomm_pcb_kill(pcb, error);
2257 mtx_unlock(&pcb->pcb_mtx);
2259 NG_BTSOCKET_RFCOMM_WARN(
2260 "%s: Got DM for non-existing dlci=%d\n", __func__, dlci);
2264 } /* ng_btsocket_rfcomm_receive_dm */
2267 * Process RFCOMM UIH frame (data)
2271 ng_btsocket_rfcomm_receive_uih(ng_btsocket_rfcomm_session_p s, int dlci,
2272 int pf, struct mbuf *m0)
2274 ng_btsocket_rfcomm_pcb_p pcb = NULL;
2277 mtx_assert(&s->session_mtx, MA_OWNED);
2279 NG_BTSOCKET_RFCOMM_INFO(
2280 "%s: Got UIH, session state=%d, flags=%#x, mtu=%d, dlci=%d, pf=%d, len=%d\n",
2281 __func__, s->state, s->flags, s->mtu, dlci, pf,
2284 /* XXX should we do it here? Check for session flow control */
2285 if (s->flags & NG_BTSOCKET_RFCOMM_SESSION_LFC) {
2286 NG_BTSOCKET_RFCOMM_WARN(
2287 "%s: Got UIH with session flow control asserted, state=%d, flags=%#x\n",
2288 __func__, s->state, s->flags);
2292 /* Check if we have this dlci */
2293 pcb = ng_btsocket_rfcomm_pcb_by_dlci(s, dlci);
2295 NG_BTSOCKET_RFCOMM_WARN(
2296 "%s: Got UIH for non-existing dlci=%d\n", __func__, dlci);
2297 error = ng_btsocket_rfcomm_send_command(s,RFCOMM_FRAME_DM,dlci);
2301 mtx_lock(&pcb->pcb_mtx);
2303 /* Check dlci state */
2304 if (pcb->state != NG_BTSOCKET_RFCOMM_DLC_CONNECTED) {
2305 NG_BTSOCKET_RFCOMM_WARN(
2306 "%s: Got UIH for dlci=%d in invalid state=%d, flags=%#x\n",
2307 __func__, dlci, pcb->state, pcb->flags);
2312 /* Check dlci flow control */
2313 if (((pcb->flags & NG_BTSOCKET_RFCOMM_DLC_CFC) && pcb->rx_cred <= 0) ||
2314 (pcb->lmodem & RFCOMM_MODEM_FC)) {
2315 NG_BTSOCKET_RFCOMM_ERR(
2316 "%s: Got UIH for dlci=%d with asserted flow control, state=%d, " \
2317 "flags=%#x, rx_cred=%d, lmodem=%#x\n",
2318 __func__, dlci, pcb->state, pcb->flags,
2319 pcb->rx_cred, pcb->lmodem);
2323 /* Did we get any credits? */
2324 if ((pcb->flags & NG_BTSOCKET_RFCOMM_DLC_CFC) && pf) {
2325 NG_BTSOCKET_RFCOMM_INFO(
2326 "%s: Got %d more credits for dlci=%d, state=%d, flags=%#x, " \
2327 "rx_cred=%d, tx_cred=%d\n",
2328 __func__, *mtod(m0, u_int8_t *), dlci, pcb->state,
2329 pcb->flags, pcb->rx_cred, pcb->tx_cred);
2331 pcb->tx_cred += *mtod(m0, u_int8_t *);
2334 /* Send more from the DLC. XXX check for errors? */
2335 ng_btsocket_rfcomm_pcb_send(pcb, ALOT);
2338 /* OK the of the rest of the mbuf is the data */
2339 if (m0->m_pkthdr.len > 0) {
2340 /* If we are using credit flow control decrease rx_cred here */
2341 if (pcb->flags & NG_BTSOCKET_RFCOMM_DLC_CFC) {
2342 /* Give remote peer more credits (if needed) */
2343 if (-- pcb->rx_cred <= RFCOMM_MAX_CREDITS / 2)
2344 ng_btsocket_rfcomm_send_credits(pcb);
2346 NG_BTSOCKET_RFCOMM_INFO(
2347 "%s: Remote side still has credits, dlci=%d, state=%d, flags=%#x, " \
2348 "rx_cred=%d, tx_cred=%d\n", __func__, dlci, pcb->state, pcb->flags,
2349 pcb->rx_cred, pcb->tx_cred);
2352 /* Check packet against mtu on dlci */
2353 if (m0->m_pkthdr.len > pcb->mtu) {
2354 NG_BTSOCKET_RFCOMM_ERR(
2355 "%s: Got oversized UIH for dlci=%d, state=%d, flags=%#x, mtu=%d, len=%d\n",
2356 __func__, dlci, pcb->state, pcb->flags,
2357 pcb->mtu, m0->m_pkthdr.len);
2360 } else if (m0->m_pkthdr.len > sbspace(&pcb->so->so_rcv)) {
2362 * This is really bad. Receive queue on socket does
2363 * not have enough space for the packet. We do not
2364 * have any other choice but drop the packet.
2367 NG_BTSOCKET_RFCOMM_ERR(
2368 "%s: Not enough space in socket receive queue. Dropping UIH for dlci=%d, " \
2369 "state=%d, flags=%#x, len=%d, space=%ld\n",
2370 __func__, dlci, pcb->state, pcb->flags,
2371 m0->m_pkthdr.len, sbspace(&pcb->so->so_rcv));
2375 /* Append packet to the socket receive queue */
2376 sbappend(&pcb->so->so_rcv, m0, 0);
2383 mtx_unlock(&pcb->pcb_mtx);
2385 NG_FREE_M(m0); /* checks for != NULL */
2388 } /* ng_btsocket_rfcomm_receive_uih */
2391 * Process RFCOMM MCC command (Multiplexor)
2393 * From TS 07.10 spec
2395 * "5.4.3.1 Information Data
2397 * ...The frames (UIH) sent by the initiating station have the C/R bit set
2398 * to 1 and those sent by the responding station have the C/R bit set to 0..."
2400 * "5.4.6.2 Operating procedures
2402 * Messages always exist in pairs; a command message and a corresponding
2403 * response message. If the C/R bit is set to 1 the message is a command,
2404 * if it is set to 0 the message is a response...
2408 * NOTE: Notice that when UIH frames are used to convey information on DLCI 0
2409 * there are at least two different fields that contain a C/R bit, and the
2410 * bits are set of different form. The C/R bit in the Type field shall be set
2411 * as it is stated above, while the C/R bit in the Address field (see subclause
2412 * 5.2.1.2) shall be set as it is described in subclause 5.4.3.1."
2416 ng_btsocket_rfcomm_receive_mcc(ng_btsocket_rfcomm_session_p s, struct mbuf *m0)
2418 struct rfcomm_mcc_hdr *hdr = NULL;
2419 u_int8_t cr, type, length;
2421 mtx_assert(&s->session_mtx, MA_OWNED);
2424 * We can access data directly in the first mbuf, because we have
2425 * m_pullup()'ed mbuf chain in ng_btsocket_rfcomm_receive_frame().
2426 * All MCC commands should fit into single mbuf (except probably TEST).
2429 hdr = mtod(m0, struct rfcomm_mcc_hdr *);
2430 cr = RFCOMM_CR(hdr->type);
2431 type = RFCOMM_MCC_TYPE(hdr->type);
2432 length = RFCOMM_MCC_LENGTH(hdr->length);
2434 /* Check MCC frame length */
2435 if (sizeof(*hdr) + length != m0->m_pkthdr.len) {
2436 NG_BTSOCKET_RFCOMM_ERR(
2437 "%s: Invalid MCC frame length=%d, len=%d\n",
2438 __func__, length, m0->m_pkthdr.len);
2445 case RFCOMM_MCC_TEST:
2446 return (ng_btsocket_rfcomm_receive_test(s, m0));
2449 case RFCOMM_MCC_FCON:
2450 case RFCOMM_MCC_FCOFF:
2451 return (ng_btsocket_rfcomm_receive_fc(s, m0));
2454 case RFCOMM_MCC_MSC:
2455 return (ng_btsocket_rfcomm_receive_msc(s, m0));
2458 case RFCOMM_MCC_RPN:
2459 return (ng_btsocket_rfcomm_receive_rpn(s, m0));
2462 case RFCOMM_MCC_RLS:
2463 return (ng_btsocket_rfcomm_receive_rls(s, m0));
2467 return (ng_btsocket_rfcomm_receive_pn(s, m0));
2470 case RFCOMM_MCC_NSC:
2471 NG_BTSOCKET_RFCOMM_ERR(
2472 "%s: Got MCC NSC, type=%#x, cr=%d, length=%d, session state=%d, flags=%#x, " \
2473 "mtu=%d, len=%d\n", __func__, RFCOMM_MCC_TYPE(*((u_int8_t *)(hdr + 1))), cr,
2474 length, s->state, s->flags, s->mtu, m0->m_pkthdr.len);
2479 NG_BTSOCKET_RFCOMM_ERR(
2480 "%s: Got unknown MCC, type=%#x, cr=%d, length=%d, session state=%d, " \
2481 "flags=%#x, mtu=%d, len=%d\n",
2482 __func__, type, cr, length, s->state, s->flags,
2483 s->mtu, m0->m_pkthdr.len);
2485 /* Reuse mbuf to send NSC */
2486 hdr = mtod(m0, struct rfcomm_mcc_hdr *);
2487 m0->m_pkthdr.len = m0->m_len = sizeof(*hdr);
2489 /* Create MCC NSC header */
2490 hdr->type = RFCOMM_MKMCC_TYPE(0, RFCOMM_MCC_NSC);
2491 hdr->length = RFCOMM_MKLEN8(1);
2493 /* Put back MCC command type we did not like */
2494 m0->m_data[m0->m_len] = RFCOMM_MKMCC_TYPE(cr, type);
2495 m0->m_pkthdr.len ++;
2498 /* Send UIH frame */
2499 return (ng_btsocket_rfcomm_send_uih(s,
2500 RFCOMM_MKADDRESS(INITIATOR(s), 0), 0, 0, m0));
2505 } /* ng_btsocket_rfcomm_receive_mcc */
2508 * Receive RFCOMM TEST MCC command
2512 ng_btsocket_rfcomm_receive_test(ng_btsocket_rfcomm_session_p s, struct mbuf *m0)
2514 struct rfcomm_mcc_hdr *hdr = mtod(m0, struct rfcomm_mcc_hdr *);
2517 mtx_assert(&s->session_mtx, MA_OWNED);
2519 NG_BTSOCKET_RFCOMM_INFO(
2520 "%s: Got MCC TEST, cr=%d, length=%d, session state=%d, flags=%#x, mtu=%d, " \
2521 "len=%d\n", __func__, RFCOMM_CR(hdr->type), RFCOMM_MCC_LENGTH(hdr->length),
2522 s->state, s->flags, s->mtu, m0->m_pkthdr.len);
2524 if (RFCOMM_CR(hdr->type)) {
2525 hdr->type = RFCOMM_MKMCC_TYPE(0, RFCOMM_MCC_TEST);
2526 error = ng_btsocket_rfcomm_send_uih(s,
2527 RFCOMM_MKADDRESS(INITIATOR(s), 0), 0, 0, m0);
2529 NG_FREE_M(m0); /* XXX ignore response */
2532 } /* ng_btsocket_rfcomm_receive_test */
2535 * Receive RFCOMM FCON/FCOFF MCC command
2539 ng_btsocket_rfcomm_receive_fc(ng_btsocket_rfcomm_session_p s, struct mbuf *m0)
2541 struct rfcomm_mcc_hdr *hdr = mtod(m0, struct rfcomm_mcc_hdr *);
2542 u_int8_t type = RFCOMM_MCC_TYPE(hdr->type);
2545 mtx_assert(&s->session_mtx, MA_OWNED);
2548 * Turn ON/OFF aggregate flow on the entire session. When remote peer
2549 * asserted flow control no transmission shall occur except on dlci 0
2550 * (control channel).
2553 NG_BTSOCKET_RFCOMM_INFO(
2554 "%s: Got MCC FC%s, cr=%d, length=%d, session state=%d, flags=%#x, mtu=%d, " \
2555 "len=%d\n", __func__, (type == RFCOMM_MCC_FCON)? "ON" : "OFF",
2556 RFCOMM_CR(hdr->type), RFCOMM_MCC_LENGTH(hdr->length),
2557 s->state, s->flags, s->mtu, m0->m_pkthdr.len);
2559 if (RFCOMM_CR(hdr->type)) {
2560 if (type == RFCOMM_MCC_FCON)
2561 s->flags &= ~NG_BTSOCKET_RFCOMM_SESSION_RFC;
2563 s->flags |= NG_BTSOCKET_RFCOMM_SESSION_RFC;
2565 hdr->type = RFCOMM_MKMCC_TYPE(0, type);
2566 error = ng_btsocket_rfcomm_send_uih(s,
2567 RFCOMM_MKADDRESS(INITIATOR(s), 0), 0, 0, m0);
2569 NG_FREE_M(m0); /* XXX ignore response */
2572 } /* ng_btsocket_rfcomm_receive_fc */
2575 * Receive RFCOMM MSC MCC command
2579 ng_btsocket_rfcomm_receive_msc(ng_btsocket_rfcomm_session_p s, struct mbuf *m0)
2581 struct rfcomm_mcc_hdr *hdr = mtod(m0, struct rfcomm_mcc_hdr*);
2582 struct rfcomm_mcc_msc *msc = (struct rfcomm_mcc_msc *)(hdr+1);
2583 ng_btsocket_rfcomm_pcb_t *pcb = NULL;
2586 mtx_assert(&s->session_mtx, MA_OWNED);
2588 NG_BTSOCKET_RFCOMM_INFO(
2589 "%s: Got MCC MSC, dlci=%d, cr=%d, length=%d, session state=%d, flags=%#x, " \
2591 __func__, RFCOMM_DLCI(msc->address), RFCOMM_CR(hdr->type),
2592 RFCOMM_MCC_LENGTH(hdr->length), s->state, s->flags,
2593 s->mtu, m0->m_pkthdr.len);
2595 if (RFCOMM_CR(hdr->type)) {
2596 pcb = ng_btsocket_rfcomm_pcb_by_dlci(s, RFCOMM_DLCI(msc->address));
2598 NG_BTSOCKET_RFCOMM_WARN(
2599 "%s: Got MSC command for non-existing dlci=%d\n",
2600 __func__, RFCOMM_DLCI(msc->address));
2606 mtx_lock(&pcb->pcb_mtx);
2608 if (pcb->state != NG_BTSOCKET_RFCOMM_DLC_CONNECTING &&
2609 pcb->state != NG_BTSOCKET_RFCOMM_DLC_CONNECTED) {
2610 NG_BTSOCKET_RFCOMM_WARN(
2611 "%s: Got MSC on dlci=%d in invalid state=%d\n",
2612 __func__, RFCOMM_DLCI(msc->address),
2615 mtx_unlock(&pcb->pcb_mtx);
2621 pcb->rmodem = msc->modem; /* Update remote port signals */
2623 hdr->type = RFCOMM_MKMCC_TYPE(0, RFCOMM_MCC_MSC);
2624 error = ng_btsocket_rfcomm_send_uih(s,
2625 RFCOMM_MKADDRESS(INITIATOR(s), 0), 0, 0, m0);
2628 /* Send more data from DLC. XXX check for errors? */
2629 if (!(pcb->rmodem & RFCOMM_MODEM_FC) &&
2630 !(pcb->flags & NG_BTSOCKET_RFCOMM_DLC_CFC))
2631 ng_btsocket_rfcomm_pcb_send(pcb, ALOT);
2634 mtx_unlock(&pcb->pcb_mtx);
2636 NG_FREE_M(m0); /* XXX ignore response */
2639 } /* ng_btsocket_rfcomm_receive_msc */
2642 * Receive RFCOMM RPN MCC command
2643 * XXX FIXME do we need htole16/le16toh for RPN param_mask?
2647 ng_btsocket_rfcomm_receive_rpn(ng_btsocket_rfcomm_session_p s, struct mbuf *m0)
2649 struct rfcomm_mcc_hdr *hdr = mtod(m0, struct rfcomm_mcc_hdr *);
2650 struct rfcomm_mcc_rpn *rpn = (struct rfcomm_mcc_rpn *)(hdr + 1);
2652 u_int16_t param_mask;
2653 u_int8_t bit_rate, data_bits, stop_bits, parity,
2654 flow_control, xon_char, xoff_char;
2656 mtx_assert(&s->session_mtx, MA_OWNED);
2658 NG_BTSOCKET_RFCOMM_INFO(
2659 "%s: Got MCC RPN, dlci=%d, cr=%d, length=%d, session state=%d, flags=%#x, " \
2661 __func__, RFCOMM_DLCI(rpn->dlci), RFCOMM_CR(hdr->type),
2662 RFCOMM_MCC_LENGTH(hdr->length), s->state, s->flags,
2663 s->mtu, m0->m_pkthdr.len);
2665 if (RFCOMM_CR(hdr->type)) {
2666 param_mask = RFCOMM_RPN_PM_ALL;
2668 if (RFCOMM_MCC_LENGTH(hdr->length) == 1) {
2669 /* Request - return default setting */
2670 bit_rate = RFCOMM_RPN_BR_115200;
2671 data_bits = RFCOMM_RPN_DATA_8;
2672 stop_bits = RFCOMM_RPN_STOP_1;
2673 parity = RFCOMM_RPN_PARITY_NONE;
2674 flow_control = RFCOMM_RPN_FLOW_NONE;
2675 xon_char = RFCOMM_RPN_XON_CHAR;
2676 xoff_char = RFCOMM_RPN_XOFF_CHAR;
2679 * Ignore/accept bit_rate, 8 bits, 1 stop bit, no
2680 * parity, no flow control lines, default XON/XOFF
2684 bit_rate = rpn->bit_rate;
2685 rpn->param_mask = le16toh(rpn->param_mask); /* XXX */
2687 data_bits = RFCOMM_RPN_DATA_BITS(rpn->line_settings);
2688 if (rpn->param_mask & RFCOMM_RPN_PM_DATA &&
2689 data_bits != RFCOMM_RPN_DATA_8) {
2690 data_bits = RFCOMM_RPN_DATA_8;
2691 param_mask ^= RFCOMM_RPN_PM_DATA;
2694 stop_bits = RFCOMM_RPN_STOP_BITS(rpn->line_settings);
2695 if (rpn->param_mask & RFCOMM_RPN_PM_STOP &&
2696 stop_bits != RFCOMM_RPN_STOP_1) {
2697 stop_bits = RFCOMM_RPN_STOP_1;
2698 param_mask ^= RFCOMM_RPN_PM_STOP;
2701 parity = RFCOMM_RPN_PARITY(rpn->line_settings);
2702 if (rpn->param_mask & RFCOMM_RPN_PM_PARITY &&
2703 parity != RFCOMM_RPN_PARITY_NONE) {
2704 parity = RFCOMM_RPN_PARITY_NONE;
2705 param_mask ^= RFCOMM_RPN_PM_PARITY;
2708 flow_control = rpn->flow_control;
2709 if (rpn->param_mask & RFCOMM_RPN_PM_FLOW &&
2710 flow_control != RFCOMM_RPN_FLOW_NONE) {
2711 flow_control = RFCOMM_RPN_FLOW_NONE;
2712 param_mask ^= RFCOMM_RPN_PM_FLOW;
2715 xon_char = rpn->xon_char;
2716 if (rpn->param_mask & RFCOMM_RPN_PM_XON &&
2717 xon_char != RFCOMM_RPN_XON_CHAR) {
2718 xon_char = RFCOMM_RPN_XON_CHAR;
2719 param_mask ^= RFCOMM_RPN_PM_XON;
2722 xoff_char = rpn->xoff_char;
2723 if (rpn->param_mask & RFCOMM_RPN_PM_XOFF &&
2724 xoff_char != RFCOMM_RPN_XOFF_CHAR) {
2725 xoff_char = RFCOMM_RPN_XOFF_CHAR;
2726 param_mask ^= RFCOMM_RPN_PM_XOFF;
2730 rpn->bit_rate = bit_rate;
2731 rpn->line_settings = RFCOMM_MKRPN_LINE_SETTINGS(data_bits,
2733 rpn->flow_control = flow_control;
2734 rpn->xon_char = xon_char;
2735 rpn->xoff_char = xoff_char;
2736 rpn->param_mask = htole16(param_mask); /* XXX */
2738 m0->m_pkthdr.len = m0->m_len = sizeof(*hdr) + sizeof(*rpn);
2740 hdr->type = RFCOMM_MKMCC_TYPE(0, RFCOMM_MCC_RPN);
2741 error = ng_btsocket_rfcomm_send_uih(s,
2742 RFCOMM_MKADDRESS(INITIATOR(s), 0), 0, 0, m0);
2744 NG_FREE_M(m0); /* XXX ignore response */
2747 } /* ng_btsocket_rfcomm_receive_rpn */
2750 * Receive RFCOMM RLS MCC command
2754 ng_btsocket_rfcomm_receive_rls(ng_btsocket_rfcomm_session_p s, struct mbuf *m0)
2756 struct rfcomm_mcc_hdr *hdr = mtod(m0, struct rfcomm_mcc_hdr *);
2757 struct rfcomm_mcc_rls *rls = (struct rfcomm_mcc_rls *)(hdr + 1);
2760 mtx_assert(&s->session_mtx, MA_OWNED);
2763 * XXX FIXME Do we have to do anything else here? Remote peer tries to
2764 * tell us something about DLCI. Just report what we have received and
2765 * return back received values as required by TS 07.10 spec.
2768 NG_BTSOCKET_RFCOMM_INFO(
2769 "%s: Got MCC RLS, dlci=%d, status=%#x, cr=%d, length=%d, session state=%d, " \
2770 "flags=%#x, mtu=%d, len=%d\n",
2771 __func__, RFCOMM_DLCI(rls->address), rls->status,
2772 RFCOMM_CR(hdr->type), RFCOMM_MCC_LENGTH(hdr->length),
2773 s->state, s->flags, s->mtu, m0->m_pkthdr.len);
2775 if (RFCOMM_CR(hdr->type)) {
2776 if (rls->status & 0x1)
2777 NG_BTSOCKET_RFCOMM_ERR(
2778 "%s: Got RLS dlci=%d, error=%#x\n", __func__, RFCOMM_DLCI(rls->address),
2781 hdr->type = RFCOMM_MKMCC_TYPE(0, RFCOMM_MCC_RLS);
2782 error = ng_btsocket_rfcomm_send_uih(s,
2783 RFCOMM_MKADDRESS(INITIATOR(s), 0), 0, 0, m0);
2785 NG_FREE_M(m0); /* XXX ignore responses */
2788 } /* ng_btsocket_rfcomm_receive_rls */
2791 * Receive RFCOMM PN MCC command
2795 ng_btsocket_rfcomm_receive_pn(ng_btsocket_rfcomm_session_p s, struct mbuf *m0)
2797 struct rfcomm_mcc_hdr *hdr = mtod(m0, struct rfcomm_mcc_hdr*);
2798 struct rfcomm_mcc_pn *pn = (struct rfcomm_mcc_pn *)(hdr+1);
2799 ng_btsocket_rfcomm_pcb_t *pcb = NULL;
2802 mtx_assert(&s->session_mtx, MA_OWNED);
2804 NG_BTSOCKET_RFCOMM_INFO(
2805 "%s: Got MCC PN, dlci=%d, cr=%d, length=%d, flow_control=%#x, priority=%d, " \
2806 "ack_timer=%d, mtu=%d, max_retrans=%d, credits=%d, session state=%d, " \
2807 "flags=%#x, session mtu=%d, len=%d\n",
2808 __func__, pn->dlci, RFCOMM_CR(hdr->type),
2809 RFCOMM_MCC_LENGTH(hdr->length), pn->flow_control, pn->priority,
2810 pn->ack_timer, le16toh(pn->mtu), pn->max_retrans, pn->credits,
2811 s->state, s->flags, s->mtu, m0->m_pkthdr.len);
2813 if (pn->dlci == 0) {
2814 NG_BTSOCKET_RFCOMM_ERR("%s: Zero dlci in MCC PN\n", __func__);
2820 /* Check if we have this dlci */
2821 pcb = ng_btsocket_rfcomm_pcb_by_dlci(s, pn->dlci);
2823 mtx_lock(&pcb->pcb_mtx);
2825 if (RFCOMM_CR(hdr->type)) {
2827 ng_btsocket_rfcomm_set_pn(pcb, 1, pn->flow_control,
2828 pn->credits, pn->mtu);
2830 if (pcb->flags & NG_BTSOCKET_RFCOMM_DLC_CFC) {
2831 pn->flow_control = 0xe0;
2832 pn->credits = RFCOMM_DEFAULT_CREDITS;
2834 pn->flow_control = 0;
2838 hdr->type = RFCOMM_MKMCC_TYPE(0, RFCOMM_MCC_PN);
2839 error = ng_btsocket_rfcomm_send_uih(s,
2840 RFCOMM_MKADDRESS(INITIATOR(s), 0),
2843 /* PN Response - proceed with SABM. Timeout still set */
2844 if (pcb->state == NG_BTSOCKET_RFCOMM_DLC_CONFIGURING) {
2845 ng_btsocket_rfcomm_set_pn(pcb, 0,
2846 pn->flow_control, pn->credits, pn->mtu);
2848 pcb->state = NG_BTSOCKET_RFCOMM_DLC_CONNECTING;
2849 error = ng_btsocket_rfcomm_send_command(s,
2850 RFCOMM_FRAME_SABM, pn->dlci);
2852 NG_BTSOCKET_RFCOMM_WARN(
2853 "%s: Got PN response for dlci=%d in invalid state=%d\n",
2854 __func__, pn->dlci, pcb->state);
2859 mtx_unlock(&pcb->pcb_mtx);
2860 } else if (RFCOMM_CR(hdr->type)) {
2861 /* PN request to non-existing dlci - incoming connection */
2862 pcb = ng_btsocket_rfcomm_connect_ind(s,
2863 RFCOMM_SRVCHANNEL(pn->dlci));
2865 mtx_lock(&pcb->pcb_mtx);
2867 pcb->dlci = pn->dlci;
2869 ng_btsocket_rfcomm_set_pn(pcb, 1, pn->flow_control,
2870 pn->credits, pn->mtu);
2872 if (pcb->flags & NG_BTSOCKET_RFCOMM_DLC_CFC) {
2873 pn->flow_control = 0xe0;
2874 pn->credits = RFCOMM_DEFAULT_CREDITS;
2876 pn->flow_control = 0;
2880 hdr->type = RFCOMM_MKMCC_TYPE(0, RFCOMM_MCC_PN);
2881 error = ng_btsocket_rfcomm_send_uih(s,
2882 RFCOMM_MKADDRESS(INITIATOR(s), 0),
2886 ng_btsocket_rfcomm_timeout(pcb);
2887 pcb->state = NG_BTSOCKET_RFCOMM_DLC_CONNECTING;
2888 soisconnecting(pcb->so);
2890 ng_btsocket_rfcomm_pcb_kill(pcb, error);
2892 mtx_unlock(&pcb->pcb_mtx);
2894 /* Nobody is listen()ing on this channel */
2895 error = ng_btsocket_rfcomm_send_command(s,
2896 RFCOMM_FRAME_DM, pn->dlci);
2900 NG_FREE_M(m0); /* XXX ignore response to non-existing dlci */
2903 } /* ng_btsocket_rfcomm_receive_pn */
2906 * Set PN parameters for dlci. Caller must hold pcb->pcb_mtx.
2908 * From Bluetooth spec.
2910 * "... The CL1 - CL4 field is completely redefined. (In TS07.10 this defines
2911 * the convergence layer to use, which is not applicable to RFCOMM. In RFCOMM,
2912 * in Bluetooth versions up to 1.0B, this field was forced to 0).
2914 * In the PN request sent prior to a DLC establishment, this field must contain
2915 * the value 15 (0xF), indicating support of credit based flow control in the
2916 * sender. See Table 5.3 below. If the PN response contains any other value
2917 * than 14 (0xE) in this field, it is inferred that the peer RFCOMM entity is
2918 * not supporting the credit based flow control feature. (This is only possible
2919 * if the peer RFCOMM implementation is only conforming to Bluetooth version
2920 * 1.0B.) If a PN request is sent on an already open DLC, then this field must
2921 * contain the value zero; it is not possible to set initial credits more
2922 * than once per DLC activation. A responding implementation must set this
2923 * field in the PN response to 14 (0xE), if (and only if) the value in the PN
2924 * request was 15..."
2928 ng_btsocket_rfcomm_set_pn(ng_btsocket_rfcomm_pcb_p pcb, u_int8_t cr,
2929 u_int8_t flow_control, u_int8_t credits, u_int16_t mtu)
2931 mtx_assert(&pcb->pcb_mtx, MA_OWNED);
2933 pcb->mtu = le16toh(mtu);
2936 if (flow_control == 0xf0) {
2937 pcb->flags |= NG_BTSOCKET_RFCOMM_DLC_CFC;
2938 pcb->tx_cred = credits;
2940 pcb->flags &= ~NG_BTSOCKET_RFCOMM_DLC_CFC;
2944 if (flow_control == 0xe0) {
2945 pcb->flags |= NG_BTSOCKET_RFCOMM_DLC_CFC;
2946 pcb->tx_cred = credits;
2948 pcb->flags &= ~NG_BTSOCKET_RFCOMM_DLC_CFC;
2953 NG_BTSOCKET_RFCOMM_INFO(
2954 "%s: cr=%d, dlci=%d, state=%d, flags=%#x, mtu=%d, rx_cred=%d, tx_cred=%d\n",
2955 __func__, cr, pcb->dlci, pcb->state, pcb->flags, pcb->mtu,
2956 pcb->rx_cred, pcb->tx_cred);
2957 } /* ng_btsocket_rfcomm_set_pn */
2960 * Send RFCOMM SABM/DISC/UA/DM frames. Caller must hold s->session_mtx
2964 ng_btsocket_rfcomm_send_command(ng_btsocket_rfcomm_session_p s,
2965 u_int8_t type, u_int8_t dlci)
2967 struct rfcomm_cmd_hdr *hdr = NULL;
2968 struct mbuf *m = NULL;
2971 mtx_assert(&s->session_mtx, MA_OWNED);
2973 NG_BTSOCKET_RFCOMM_INFO(
2974 "%s: Sending command type %#x, session state=%d, flags=%#x, mtu=%d, dlci=%d\n",
2975 __func__, type, s->state, s->flags, s->mtu, dlci);
2978 case RFCOMM_FRAME_SABM:
2979 case RFCOMM_FRAME_DISC:
2983 case RFCOMM_FRAME_UA:
2984 case RFCOMM_FRAME_DM:
2989 panic("%s: Invalid frame type=%#x\n", __func__, type);
2994 MGETHDR(m, M_NOWAIT, MT_DATA);
2998 m->m_pkthdr.len = m->m_len = sizeof(*hdr);
3000 hdr = mtod(m, struct rfcomm_cmd_hdr *);
3001 hdr->address = RFCOMM_MKADDRESS(cr, dlci);
3002 hdr->control = RFCOMM_MKCONTROL(type, 1);
3003 hdr->length = RFCOMM_MKLEN8(0);
3004 hdr->fcs = ng_btsocket_rfcomm_fcs3((u_int8_t *) hdr);
3006 NG_BT_MBUFQ_ENQUEUE(&s->outq, m);
3009 } /* ng_btsocket_rfcomm_send_command */
3012 * Send RFCOMM UIH frame. Caller must hold s->session_mtx
3016 ng_btsocket_rfcomm_send_uih(ng_btsocket_rfcomm_session_p s, u_int8_t address,
3017 u_int8_t pf, u_int8_t credits, struct mbuf *data)
3019 struct rfcomm_frame_hdr *hdr = NULL;
3020 struct mbuf *m = NULL, *mcrc = NULL;
3023 mtx_assert(&s->session_mtx, MA_OWNED);
3025 MGETHDR(m, M_NOWAIT, MT_DATA);
3030 m->m_pkthdr.len = m->m_len = sizeof(*hdr);
3032 MGET(mcrc, M_NOWAIT, MT_DATA);
3039 /* Fill UIH frame header */
3040 hdr = mtod(m, struct rfcomm_frame_hdr *);
3041 hdr->address = address;
3042 hdr->control = RFCOMM_MKCONTROL(RFCOMM_FRAME_UIH, pf);
3045 mcrc->m_data[0] = ng_btsocket_rfcomm_fcs2((u_int8_t *) hdr);
3047 /* Put length back */
3048 length = (data != NULL)? data->m_pkthdr.len : 0;
3050 u_int16_t l = htole16(RFCOMM_MKLEN16(length));
3052 bcopy(&l, &hdr->length, sizeof(l));
3056 hdr->length = RFCOMM_MKLEN8(length);
3059 m->m_data[m->m_len] = credits;
3067 m->m_pkthdr.len += length;
3074 NG_BTSOCKET_RFCOMM_INFO(
3075 "%s: Sending UIH state=%d, flags=%#x, address=%d, length=%d, pf=%d, " \
3076 "credits=%d, len=%d\n",
3077 __func__, s->state, s->flags, address, length, pf, credits,
3080 NG_BT_MBUFQ_ENQUEUE(&s->outq, m);
3083 } /* ng_btsocket_rfcomm_send_uih */
3086 * Send MSC request. Caller must hold pcb->pcb_mtx and pcb->session->session_mtx
3090 ng_btsocket_rfcomm_send_msc(ng_btsocket_rfcomm_pcb_p pcb)
3092 struct mbuf *m = NULL;
3093 struct rfcomm_mcc_hdr *hdr = NULL;
3094 struct rfcomm_mcc_msc *msc = NULL;
3096 mtx_assert(&pcb->session->session_mtx, MA_OWNED);
3097 mtx_assert(&pcb->pcb_mtx, MA_OWNED);
3099 MGETHDR(m, M_NOWAIT, MT_DATA);
3103 m->m_pkthdr.len = m->m_len = sizeof(*hdr) + sizeof(*msc);
3105 hdr = mtod(m, struct rfcomm_mcc_hdr *);
3106 msc = (struct rfcomm_mcc_msc *)(hdr + 1);
3108 hdr->type = RFCOMM_MKMCC_TYPE(1, RFCOMM_MCC_MSC);
3109 hdr->length = RFCOMM_MKLEN8(sizeof(*msc));
3111 msc->address = RFCOMM_MKADDRESS(1, pcb->dlci);
3112 msc->modem = pcb->lmodem;
3114 NG_BTSOCKET_RFCOMM_INFO(
3115 "%s: Sending MSC dlci=%d, state=%d, flags=%#x, address=%d, modem=%#x\n",
3116 __func__, pcb->dlci, pcb->state, pcb->flags, msc->address,
3119 return (ng_btsocket_rfcomm_send_uih(pcb->session,
3120 RFCOMM_MKADDRESS(INITIATOR(pcb->session), 0), 0, 0, m));
3121 } /* ng_btsocket_rfcomm_send_msc */
3124 * Send PN request. Caller must hold pcb->pcb_mtx and pcb->session->session_mtx
3128 ng_btsocket_rfcomm_send_pn(ng_btsocket_rfcomm_pcb_p pcb)
3130 struct mbuf *m = NULL;
3131 struct rfcomm_mcc_hdr *hdr = NULL;
3132 struct rfcomm_mcc_pn *pn = NULL;
3134 mtx_assert(&pcb->session->session_mtx, MA_OWNED);
3135 mtx_assert(&pcb->pcb_mtx, MA_OWNED);
3137 MGETHDR(m, M_NOWAIT, MT_DATA);
3141 m->m_pkthdr.len = m->m_len = sizeof(*hdr) + sizeof(*pn);
3143 hdr = mtod(m, struct rfcomm_mcc_hdr *);
3144 pn = (struct rfcomm_mcc_pn *)(hdr + 1);
3146 hdr->type = RFCOMM_MKMCC_TYPE(1, RFCOMM_MCC_PN);
3147 hdr->length = RFCOMM_MKLEN8(sizeof(*pn));
3149 pn->dlci = pcb->dlci;
3152 * Set default DLCI priority as described in GSM 07.10
3153 * (ETSI TS 101 369) clause 5.6 page 42
3156 pn->priority = (pcb->dlci < 56)? (((pcb->dlci >> 3) << 3) + 7) : 61;
3158 pn->mtu = htole16(pcb->mtu);
3159 pn->max_retrans = 0;
3161 if (pcb->flags & NG_BTSOCKET_RFCOMM_DLC_CFC) {
3162 pn->flow_control = 0xf0;
3163 pn->credits = pcb->rx_cred;
3165 pn->flow_control = 0;
3169 NG_BTSOCKET_RFCOMM_INFO(
3170 "%s: Sending PN dlci=%d, state=%d, flags=%#x, mtu=%d, flow_control=%#x, " \
3171 "credits=%d\n", __func__, pcb->dlci, pcb->state, pcb->flags, pcb->mtu,
3172 pn->flow_control, pn->credits);
3174 return (ng_btsocket_rfcomm_send_uih(pcb->session,
3175 RFCOMM_MKADDRESS(INITIATOR(pcb->session), 0), 0, 0, m));
3176 } /* ng_btsocket_rfcomm_send_pn */
3179 * Calculate and send credits based on available space in receive buffer
3183 ng_btsocket_rfcomm_send_credits(ng_btsocket_rfcomm_pcb_p pcb)
3188 mtx_assert(&pcb->pcb_mtx, MA_OWNED);
3189 mtx_assert(&pcb->session->session_mtx, MA_OWNED);
3191 NG_BTSOCKET_RFCOMM_INFO(
3192 "%s: Sending more credits, dlci=%d, state=%d, flags=%#x, mtu=%d, " \
3193 "space=%ld, tx_cred=%d, rx_cred=%d\n",
3194 __func__, pcb->dlci, pcb->state, pcb->flags, pcb->mtu,
3195 sbspace(&pcb->so->so_rcv), pcb->tx_cred, pcb->rx_cred);
3197 credits = sbspace(&pcb->so->so_rcv) / pcb->mtu;
3199 if (pcb->rx_cred + credits > RFCOMM_MAX_CREDITS)
3200 credits = RFCOMM_MAX_CREDITS - pcb->rx_cred;
3202 error = ng_btsocket_rfcomm_send_uih(
3204 RFCOMM_MKADDRESS(INITIATOR(pcb->session),
3205 pcb->dlci), 1, credits, NULL);
3207 pcb->rx_cred += credits;
3209 NG_BTSOCKET_RFCOMM_INFO(
3210 "%s: Gave remote side %d more credits, dlci=%d, state=%d, flags=%#x, " \
3211 "rx_cred=%d, tx_cred=%d\n", __func__, credits, pcb->dlci, pcb->state,
3212 pcb->flags, pcb->rx_cred, pcb->tx_cred);
3214 NG_BTSOCKET_RFCOMM_ERR(
3215 "%s: Could not send credits, error=%d, dlci=%d, state=%d, flags=%#x, " \
3216 "mtu=%d, space=%ld, tx_cred=%d, rx_cred=%d\n",
3217 __func__, error, pcb->dlci, pcb->state,
3218 pcb->flags, pcb->mtu, sbspace(&pcb->so->so_rcv),
3219 pcb->tx_cred, pcb->rx_cred);
3223 } /* ng_btsocket_rfcomm_send_credits */
3225 /*****************************************************************************
3226 *****************************************************************************
3228 *****************************************************************************
3229 *****************************************************************************/
3232 * Send data from socket send buffer
3233 * Caller must hold pcb->pcb_mtx and pcb->session->session_mtx
3237 ng_btsocket_rfcomm_pcb_send(ng_btsocket_rfcomm_pcb_p pcb, int limit)
3239 struct mbuf *m = NULL;
3240 int sent, length, error;
3242 mtx_assert(&pcb->session->session_mtx, MA_OWNED);
3243 mtx_assert(&pcb->pcb_mtx, MA_OWNED);
3245 if (pcb->flags & NG_BTSOCKET_RFCOMM_DLC_CFC)
3246 limit = min(limit, pcb->tx_cred);
3247 else if (!(pcb->rmodem & RFCOMM_MODEM_FC))
3248 limit = min(limit, RFCOMM_MAX_CREDITS); /* XXX ??? */
3253 NG_BTSOCKET_RFCOMM_INFO(
3254 "%s: Could not send - remote flow control asserted, dlci=%d, flags=%#x, " \
3255 "rmodem=%#x, tx_cred=%d\n",
3256 __func__, pcb->dlci, pcb->flags, pcb->rmodem,
3262 for (error = 0, sent = 0; sent < limit; sent ++) {
3263 length = min(pcb->mtu, sbavail(&pcb->so->so_snd));
3267 /* Get the chunk from the socket's send buffer */
3268 m = ng_btsocket_rfcomm_prepare_packet(&pcb->so->so_snd, length);
3274 sbdrop(&pcb->so->so_snd, length);
3276 error = ng_btsocket_rfcomm_send_uih(pcb->session,
3277 RFCOMM_MKADDRESS(INITIATOR(pcb->session),
3278 pcb->dlci), 0, 0, m);
3283 if (pcb->flags & NG_BTSOCKET_RFCOMM_DLC_CFC)
3284 pcb->tx_cred -= sent;
3286 if (error == 0 && sent > 0) {
3287 pcb->flags &= ~NG_BTSOCKET_RFCOMM_DLC_SENDING;
3292 } /* ng_btsocket_rfcomm_pcb_send */
3295 * Unlink and disconnect DLC. If ng_btsocket_rfcomm_pcb_kill() returns
3296 * non zero value than socket has no reference and has to be detached.
3297 * Caller must hold pcb->pcb_mtx and pcb->session->session_mtx
3301 ng_btsocket_rfcomm_pcb_kill(ng_btsocket_rfcomm_pcb_p pcb, int error)
3303 ng_btsocket_rfcomm_session_p s = pcb->session;
3305 NG_BTSOCKET_RFCOMM_INFO(
3306 "%s: Killing DLC, so=%p, dlci=%d, state=%d, flags=%#x, error=%d\n",
3307 __func__, pcb->so, pcb->dlci, pcb->state, pcb->flags, error);
3309 if (pcb->session == NULL)
3310 panic("%s: DLC without session, pcb=%p, state=%d, flags=%#x\n",
3311 __func__, pcb, pcb->state, pcb->flags);
3313 mtx_assert(&pcb->session->session_mtx, MA_OWNED);
3314 mtx_assert(&pcb->pcb_mtx, MA_OWNED);
3316 if (pcb->flags & NG_BTSOCKET_RFCOMM_DLC_TIMO)
3317 ng_btsocket_rfcomm_untimeout(pcb);
3319 /* Detach DLC from the session. Does not matter which state DLC in */
3320 LIST_REMOVE(pcb, session_next);
3321 pcb->session = NULL;
3323 /* Change DLC state and wakeup all sleepers */
3324 pcb->state = NG_BTSOCKET_RFCOMM_DLC_CLOSED;
3325 pcb->so->so_error = error;
3326 soisdisconnected(pcb->so);
3327 wakeup(&pcb->state);
3329 /* Check if we have any DLCs left on the session */
3330 if (LIST_EMPTY(&s->dlcs) && INITIATOR(s)) {
3331 NG_BTSOCKET_RFCOMM_INFO(
3332 "%s: Disconnecting session, state=%d, flags=%#x, mtu=%d\n",
3333 __func__, s->state, s->flags, s->mtu);
3336 case NG_BTSOCKET_RFCOMM_SESSION_CLOSED:
3337 case NG_BTSOCKET_RFCOMM_SESSION_DISCONNECTING:
3339 * Do not have to do anything here. We can get here
3340 * when L2CAP connection was terminated or we have
3341 * received DISC on multiplexor channel
3345 case NG_BTSOCKET_RFCOMM_SESSION_OPEN:
3346 /* Send DISC on multiplexor channel */
3347 error = ng_btsocket_rfcomm_send_command(s,
3348 RFCOMM_FRAME_DISC, 0);
3350 s->state = NG_BTSOCKET_RFCOMM_SESSION_DISCONNECTING;
3355 case NG_BTSOCKET_RFCOMM_SESSION_CONNECTING:
3356 case NG_BTSOCKET_RFCOMM_SESSION_CONNECTED:
3357 s->state = NG_BTSOCKET_RFCOMM_SESSION_CLOSED;
3360 /* case NG_BTSOCKET_RFCOMM_SESSION_LISTENING: */
3362 panic("%s: Invalid session state=%d, flags=%#x\n",
3363 __func__, s->state, s->flags);
3367 ng_btsocket_rfcomm_task_wakeup();
3369 } /* ng_btsocket_rfcomm_pcb_kill */
3372 * Look for given dlci for given RFCOMM session. Caller must hold s->session_mtx
3375 static ng_btsocket_rfcomm_pcb_p
3376 ng_btsocket_rfcomm_pcb_by_dlci(ng_btsocket_rfcomm_session_p s, int dlci)
3378 ng_btsocket_rfcomm_pcb_p pcb = NULL;
3380 mtx_assert(&s->session_mtx, MA_OWNED);
3382 LIST_FOREACH(pcb, &s->dlcs, session_next)
3383 if (pcb->dlci == dlci)
3387 } /* ng_btsocket_rfcomm_pcb_by_dlci */
3390 * Look for socket that listens on given src address and given channel
3393 static ng_btsocket_rfcomm_pcb_p
3394 ng_btsocket_rfcomm_pcb_listener(bdaddr_p src, int channel)
3396 ng_btsocket_rfcomm_pcb_p pcb = NULL, pcb1 = NULL;
3398 mtx_lock(&ng_btsocket_rfcomm_sockets_mtx);
3400 LIST_FOREACH(pcb, &ng_btsocket_rfcomm_sockets, next) {
3401 if (pcb->channel != channel ||
3402 !(pcb->so->so_options & SO_ACCEPTCONN))
3405 if (bcmp(&pcb->src, src, sizeof(*src)) == 0)
3408 if (bcmp(&pcb->src, NG_HCI_BDADDR_ANY, sizeof(bdaddr_t)) == 0)
3412 mtx_unlock(&ng_btsocket_rfcomm_sockets_mtx);
3414 return ((pcb != NULL)? pcb : pcb1);
3415 } /* ng_btsocket_rfcomm_pcb_listener */
3417 /*****************************************************************************
3418 *****************************************************************************
3420 *****************************************************************************
3421 *****************************************************************************/
3424 * Set timeout. Caller MUST hold pcb_mtx
3428 ng_btsocket_rfcomm_timeout(ng_btsocket_rfcomm_pcb_p pcb)
3430 mtx_assert(&pcb->pcb_mtx, MA_OWNED);
3432 if (!(pcb->flags & NG_BTSOCKET_RFCOMM_DLC_TIMO)) {
3433 pcb->flags |= NG_BTSOCKET_RFCOMM_DLC_TIMO;
3434 pcb->flags &= ~NG_BTSOCKET_RFCOMM_DLC_TIMEDOUT;
3435 callout_reset(&pcb->timo, ng_btsocket_rfcomm_timo * hz,
3436 ng_btsocket_rfcomm_process_timeout, pcb);
3438 panic("%s: Duplicated socket timeout?!\n", __func__);
3439 } /* ng_btsocket_rfcomm_timeout */
3442 * Unset pcb timeout. Caller MUST hold pcb_mtx
3446 ng_btsocket_rfcomm_untimeout(ng_btsocket_rfcomm_pcb_p pcb)
3448 mtx_assert(&pcb->pcb_mtx, MA_OWNED);
3450 if (pcb->flags & NG_BTSOCKET_RFCOMM_DLC_TIMO) {
3451 callout_stop(&pcb->timo);
3452 pcb->flags &= ~NG_BTSOCKET_RFCOMM_DLC_TIMO;
3453 pcb->flags &= ~NG_BTSOCKET_RFCOMM_DLC_TIMEDOUT;
3455 panic("%s: No socket timeout?!\n", __func__);
3456 } /* ng_btsocket_rfcomm_timeout */
3459 * Process pcb timeout
3463 ng_btsocket_rfcomm_process_timeout(void *xpcb)
3465 ng_btsocket_rfcomm_pcb_p pcb = (ng_btsocket_rfcomm_pcb_p) xpcb;
3467 mtx_assert(&pcb->pcb_mtx, MA_OWNED);
3469 NG_BTSOCKET_RFCOMM_INFO(
3470 "%s: Timeout, so=%p, dlci=%d, state=%d, flags=%#x\n",
3471 __func__, pcb->so, pcb->dlci, pcb->state, pcb->flags);
3473 pcb->flags &= ~NG_BTSOCKET_RFCOMM_DLC_TIMO;
3474 pcb->flags |= NG_BTSOCKET_RFCOMM_DLC_TIMEDOUT;
3476 switch (pcb->state) {
3477 case NG_BTSOCKET_RFCOMM_DLC_CONFIGURING:
3478 case NG_BTSOCKET_RFCOMM_DLC_CONNECTING:
3479 pcb->state = NG_BTSOCKET_RFCOMM_DLC_DISCONNECTING;
3482 case NG_BTSOCKET_RFCOMM_DLC_W4_CONNECT:
3483 case NG_BTSOCKET_RFCOMM_DLC_DISCONNECTING:
3488 "%s: DLC timeout in invalid state, dlci=%d, state=%d, flags=%#x\n",
3489 __func__, pcb->dlci, pcb->state, pcb->flags);
3493 ng_btsocket_rfcomm_task_wakeup();
3494 } /* ng_btsocket_rfcomm_process_timeout */
3497 * Get up to length bytes from the socket buffer
3500 static struct mbuf *
3501 ng_btsocket_rfcomm_prepare_packet(struct sockbuf *sb, int length)
3503 struct mbuf *top = NULL, *m = NULL, *n = NULL, *nextpkt = NULL;
3504 int mlen, noff, len;
3506 MGETHDR(top, M_NOWAIT, MT_DATA);
3510 top->m_pkthdr.len = length;
3516 nextpkt = n->m_nextpkt;
3519 while (length > 0 && n != NULL) {
3520 len = min(mlen - m->m_len, n->m_len - noff);
3524 bcopy(mtod(n, caddr_t)+noff, mtod(m, caddr_t)+m->m_len, len);
3529 if (length > 0 && m->m_len == mlen) {
3530 MGET(m->m_next, M_NOWAIT, MT_DATA);
3531 if (m->m_next == NULL) {
3541 if (noff == n->m_len) {
3548 nextpkt = (n != NULL)? n->m_nextpkt : NULL;
3553 panic("%s: length=%d\n", __func__, length);
3554 if (length > 0 && n == NULL)
3555 panic("%s: bogus length=%d, n=%p\n", __func__, length, n);
3558 } /* ng_btsocket_rfcomm_prepare_packet */