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