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