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