Merge branch 'vendor/LIBPCAP' and updated build for new version.
[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  * $DragonFly: src/sys/netgraph7/bluetooth/socket/ng_btsocket_rfcomm.c,v 1.2 2008/06/26 23:05:40 dillon Exp $
33  */
34
35 #include <sys/param.h>
36 #include <sys/systm.h>
37 #include <sys/bitstring.h>
38 #include <sys/domain.h>
39 #include <sys/endian.h>
40 #include <sys/errno.h>
41 #include <sys/filedesc.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 "ng_message.h"
56 #include "netgraph.h"
57 #include "bluetooth/include/ng_bluetooth.h"
58 #include "bluetooth/include/ng_hci.h"
59 #include "bluetooth/include/ng_l2cap.h"
60 #include "bluetooth/include/ng_btsocket.h"
61 #include "bluetooth/include/ng_btsocket_l2cap.h"
62 #include "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_WAITOK | M_NULLOK | 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_WAITOK | M_NULLOK);
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_WAITOK | M_NULLOK);
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_WAITOK | M_NULLOK | 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, NULL, &flags);
1601                 if (error != 0) {
1602                         if (error == EWOULDBLOCK)
1603                                 return (0); /* XXX can happen? */
1604
1605                         NG_BTSOCKET_RFCOMM_ERR(
1606 "%s: Could not receive data from L2CAP socket, error=%d\n", __func__, error);
1607
1608                         return (error);
1609                 }
1610         
1611                 more = (m->m_nextpkt != NULL);
1612                 m->m_nextpkt = NULL;
1613
1614                 ng_btsocket_rfcomm_receive_frame(s, m);
1615         }
1616
1617         return (0);
1618 } /* ng_btsocket_rfcomm_session_receive */
1619
1620 /*
1621  * Send data on RFCOMM session
1622  * XXX FIXME locking for "l2so"?
1623  */
1624
1625 static int
1626 ng_btsocket_rfcomm_session_send(ng_btsocket_rfcomm_session_p s)
1627 {
1628         struct mbuf     *m = NULL;
1629         int              error;
1630
1631         mtx_assert(&s->session_mtx, MA_OWNED);
1632
1633         /* Send as much as we can from the session queue */
1634         while (sowriteable(s->l2so)) {
1635                 /* Check if socket still OK */
1636                 if ((error = s->l2so->so_error) != 0) {
1637                         s->l2so->so_error = 0;
1638
1639                         NG_BTSOCKET_RFCOMM_ERR(
1640 "%s: Detected error=%d on L2CAP socket, state=%d, flags=%#x\n",
1641                                 __func__, error, s->state, s->flags);
1642
1643                         return (error);
1644                 }
1645
1646                 NG_BT_MBUFQ_DEQUEUE(&s->outq, m);
1647                 if (m == NULL)
1648                         return (0); /* we are done */
1649
1650                 /* Call send function on the L2CAP socket */
1651                 error = (*s->l2so->so_proto->pr_usrreqs->pru_send)(s->l2so,
1652                                 0, m, NULL, NULL, curthread /* XXX */);
1653                 if (error != 0) {
1654                         NG_BTSOCKET_RFCOMM_ERR(
1655 "%s: Could not send data to L2CAP socket, error=%d\n", __func__, error);
1656
1657                         return (error);
1658                 }
1659         }
1660
1661         return (0);
1662 } /* ng_btsocket_rfcomm_session_send */
1663
1664 /*
1665  * Close and disconnect all DLCs for the given session. Caller must hold 
1666  * s->sesson_mtx. Will wakeup session.
1667  */
1668
1669 static void
1670 ng_btsocket_rfcomm_session_clean(ng_btsocket_rfcomm_session_p s)
1671 {
1672         ng_btsocket_rfcomm_pcb_p        pcb = NULL, pcb_next = NULL;
1673         int                             error;
1674
1675         mtx_assert(&s->session_mtx, MA_OWNED);
1676
1677         /*
1678          * Note: cannot use LIST_FOREACH because ng_btsocket_rfcomm_pcb_kill
1679          * will unlink DLC from the session
1680          */
1681
1682         for (pcb = LIST_FIRST(&s->dlcs); pcb != NULL; ) {
1683                 mtx_lock(&pcb->pcb_mtx);
1684                 pcb_next = LIST_NEXT(pcb, session_next);
1685
1686                 NG_BTSOCKET_RFCOMM_INFO(
1687 "%s: Disconnecting dlci=%d, state=%d, flags=%#x\n",
1688                         __func__, pcb->dlci, pcb->state, pcb->flags);
1689
1690                 if (pcb->state == NG_BTSOCKET_RFCOMM_DLC_CONNECTED)
1691                         error = ECONNRESET;
1692                 else
1693                         error = ECONNREFUSED;
1694
1695                 ng_btsocket_rfcomm_pcb_kill(pcb, error);
1696
1697                 mtx_unlock(&pcb->pcb_mtx);
1698                 pcb = pcb_next;
1699         }
1700 } /* ng_btsocket_rfcomm_session_clean */
1701
1702 /*
1703  * Process all DLCs on the session. Caller MUST hold s->session_mtx.
1704  */
1705
1706 static void
1707 ng_btsocket_rfcomm_session_process_pcb(ng_btsocket_rfcomm_session_p s)
1708 {
1709         ng_btsocket_rfcomm_pcb_p        pcb = NULL, pcb_next = NULL;
1710         int                             error;
1711
1712         mtx_assert(&s->session_mtx, MA_OWNED);
1713
1714         /*
1715          * Note: cannot use LIST_FOREACH because ng_btsocket_rfcomm_pcb_kill
1716          * will unlink DLC from the session
1717          */
1718
1719         for (pcb = LIST_FIRST(&s->dlcs); pcb != NULL; ) {
1720                 mtx_lock(&pcb->pcb_mtx);
1721                 pcb_next = LIST_NEXT(pcb, session_next);
1722
1723                 switch (pcb->state) {
1724
1725                 /*
1726                  * If DLC in W4_CONNECT state then we should check for both
1727                  * timeout and detach.
1728                  */
1729
1730                 case NG_BTSOCKET_RFCOMM_DLC_W4_CONNECT:
1731                         if (pcb->flags & NG_BTSOCKET_RFCOMM_DLC_DETACHED)
1732                                 ng_btsocket_rfcomm_pcb_kill(pcb, 0);
1733                         else if (pcb->flags & NG_BTSOCKET_RFCOMM_DLC_TIMEDOUT)
1734                                 ng_btsocket_rfcomm_pcb_kill(pcb, ETIMEDOUT);
1735                         break;
1736
1737                 /*
1738                  * If DLC in CONFIGURING or CONNECTING state then we only
1739                  * should check for timeout. If detach() was called then
1740                  * DLC will be moved into DISCONNECTING state.
1741                  */
1742
1743                 case NG_BTSOCKET_RFCOMM_DLC_CONFIGURING:
1744                 case NG_BTSOCKET_RFCOMM_DLC_CONNECTING:
1745                         if (pcb->flags & NG_BTSOCKET_RFCOMM_DLC_TIMEDOUT)
1746                                 ng_btsocket_rfcomm_pcb_kill(pcb, ETIMEDOUT);
1747                         break;
1748
1749                 /*
1750                  * If DLC in CONNECTED state then we need to send data (if any)
1751                  * from the socket's send queue. Note that we will send data
1752                  * from either all sockets or none. This may overload session's
1753                  * outgoing queue (but we do not check for that).
1754                  *
1755                  * XXX FIXME need scheduler for RFCOMM sockets
1756                  */
1757
1758                 case NG_BTSOCKET_RFCOMM_DLC_CONNECTED:
1759                         error = ng_btsocket_rfcomm_pcb_send(pcb, ALOT);
1760                         if (error != 0)
1761                                 ng_btsocket_rfcomm_pcb_kill(pcb, error);
1762                         break;
1763
1764                 /*
1765                  * If DLC in DISCONNECTING state then we must send DISC frame.
1766                  * Note that if DLC has timeout set then we do not need to 
1767                  * resend DISC frame.
1768                  *
1769                  * XXX FIXME need to drain all data from the socket's queue
1770                  * if LINGER option was set
1771                  */
1772
1773                 case NG_BTSOCKET_RFCOMM_DLC_DISCONNECTING:
1774                         if (!(pcb->flags & NG_BTSOCKET_RFCOMM_DLC_TIMO)) {
1775                                 error = ng_btsocket_rfcomm_send_command(
1776                                                 pcb->session, RFCOMM_FRAME_DISC,
1777                                                 pcb->dlci);
1778                                 if (error == 0)
1779                                         ng_btsocket_rfcomm_timeout(pcb);
1780                                 else
1781                                         ng_btsocket_rfcomm_pcb_kill(pcb, error);
1782                         } else if (pcb->flags & NG_BTSOCKET_RFCOMM_DLC_TIMEDOUT)
1783                                 ng_btsocket_rfcomm_pcb_kill(pcb, ETIMEDOUT);
1784                         break;
1785                 
1786 /*              case NG_BTSOCKET_RFCOMM_DLC_CLOSED: */
1787                 default:
1788                         panic("%s: Invalid DLC state=%d, flags=%#x\n",
1789                                 __func__, pcb->state, pcb->flags);
1790                         break;
1791                 }
1792
1793                 mtx_unlock(&pcb->pcb_mtx);
1794                 pcb = pcb_next;
1795         }
1796 } /* ng_btsocket_rfcomm_session_process_pcb */
1797
1798 /*
1799  * Find RFCOMM session between "src" and "dst".
1800  * Caller MUST hold ng_btsocket_rfcomm_sessions_mtx.
1801  */
1802
1803 static ng_btsocket_rfcomm_session_p
1804 ng_btsocket_rfcomm_session_by_addr(bdaddr_p src, bdaddr_p dst)
1805 {
1806         ng_btsocket_rfcomm_session_p    s = NULL;
1807         ng_btsocket_l2cap_pcb_p         l2pcb = NULL;
1808         int                             any_src;
1809
1810         mtx_assert(&ng_btsocket_rfcomm_sessions_mtx, MA_OWNED);
1811
1812         any_src = (bcmp(src, NG_HCI_BDADDR_ANY, sizeof(*src)) == 0);
1813
1814         LIST_FOREACH(s, &ng_btsocket_rfcomm_sessions, next) {
1815                 l2pcb = so2l2cap_pcb(s->l2so);
1816
1817                 if ((any_src || bcmp(&l2pcb->src, src, sizeof(*src)) == 0) &&
1818                     bcmp(&l2pcb->dst, dst, sizeof(*dst)) == 0)
1819                         break;
1820         }
1821
1822         return (s);
1823 } /* ng_btsocket_rfcomm_session_by_addr */
1824
1825 /*****************************************************************************
1826  *****************************************************************************
1827  **                                  RFCOMM 
1828  *****************************************************************************
1829  *****************************************************************************/
1830
1831 /*
1832  * Process incoming RFCOMM frame. Caller must hold s->session_mtx.
1833  * XXX FIXME check frame length
1834  */
1835
1836 static int
1837 ng_btsocket_rfcomm_receive_frame(ng_btsocket_rfcomm_session_p s,
1838                 struct mbuf *m0)
1839 {
1840         struct rfcomm_frame_hdr *hdr = NULL;
1841         struct mbuf             *m = NULL;
1842         u_int16_t                length;
1843         u_int8_t                 dlci, type;
1844         int                      error = 0;
1845
1846         mtx_assert(&s->session_mtx, MA_OWNED);
1847
1848         /* Pullup as much as we can into first mbuf (for direct access) */
1849         length = min(m0->m_pkthdr.len, MHLEN);
1850         if (m0->m_len < length) {
1851                 if ((m0 = m_pullup(m0, length)) == NULL) {
1852                         NG_BTSOCKET_RFCOMM_ALERT(
1853 "%s: m_pullup(%d) failed\n", __func__, length);
1854
1855                         return (ENOBUFS);
1856                 }
1857         }
1858
1859         hdr = mtod(m0, struct rfcomm_frame_hdr *);
1860         dlci = RFCOMM_DLCI(hdr->address);
1861         type = RFCOMM_TYPE(hdr->control);
1862
1863         /* Test EA bit in length. If not set then we have 2 bytes of length */
1864         if (!RFCOMM_EA(hdr->length)) {
1865                 bcopy(&hdr->length, &length, sizeof(length));
1866                 length = le16toh(length) >> 1;
1867                 m_adj(m0, sizeof(*hdr) + 1);
1868         } else {
1869                 length = hdr->length >> 1;
1870                 m_adj(m0, sizeof(*hdr));
1871         }
1872
1873         NG_BTSOCKET_RFCOMM_INFO(
1874 "%s: Got frame type=%#x, dlci=%d, length=%d, cr=%d, pf=%d, len=%d\n",
1875                 __func__, type, dlci, length, RFCOMM_CR(hdr->address),
1876                 RFCOMM_PF(hdr->control), m0->m_pkthdr.len);
1877
1878         /*
1879          * Get FCS (the last byte in the frame)
1880          * XXX this will not work if mbuf chain ends with empty mbuf.
1881          * XXX let's hope it never happens :)
1882          */
1883
1884         for (m = m0; m->m_next != NULL; m = m->m_next)
1885                 ;
1886         if (m->m_len <= 0)
1887                 panic("%s: Empty mbuf at the end of the chain, len=%d\n",
1888                         __func__, m->m_len);
1889
1890         /*
1891          * Check FCS. We only need to calculate FCS on first 2 or 3 bytes
1892          * and already m_pullup'ed mbuf chain, so it should be safe.
1893          */
1894
1895         if (ng_btsocket_rfcomm_check_fcs((u_int8_t *) hdr, type, m->m_data[m->m_len - 1])) {
1896                 NG_BTSOCKET_RFCOMM_ERR(
1897 "%s: Invalid RFCOMM packet. Bad checksum\n", __func__);
1898                 NG_FREE_M(m0);
1899
1900                 return (EINVAL);
1901         }
1902
1903         m_adj(m0, -1); /* Trim FCS byte */
1904
1905         /*
1906          * Process RFCOMM frame.
1907          *
1908          * From TS 07.10 spec
1909          * 
1910          * "... In the case where a SABM or DISC command with the P bit set
1911          * to 0 is received then the received frame shall be discarded..."
1912          *
1913          * "... If a unsolicited DM response is received then the frame shall
1914          * be processed irrespective of the P/F setting... "
1915          *
1916          * "... The station may transmit response frames with the F bit set 
1917          * to 0 at any opportunity on an asynchronous basis. However, in the 
1918          * case where a UA response is received with the F bit set to 0 then 
1919          * the received frame shall be discarded..."
1920          *
1921          * From Bluetooth spec
1922          *
1923          * "... When credit based flow control is being used, the meaning of
1924          * the P/F bit in the control field of the RFCOMM header is redefined
1925          * for UIH frames..."
1926          */
1927
1928         switch (type) {
1929         case RFCOMM_FRAME_SABM:
1930                 if (RFCOMM_PF(hdr->control))
1931                         error = ng_btsocket_rfcomm_receive_sabm(s, dlci);
1932                 break;
1933
1934         case RFCOMM_FRAME_DISC:
1935                 if (RFCOMM_PF(hdr->control))
1936                         error = ng_btsocket_rfcomm_receive_disc(s, dlci);
1937                 break;
1938
1939         case RFCOMM_FRAME_UA:
1940                 if (RFCOMM_PF(hdr->control))
1941                         error = ng_btsocket_rfcomm_receive_ua(s, dlci);
1942                 break;
1943
1944         case RFCOMM_FRAME_DM:
1945                 error = ng_btsocket_rfcomm_receive_dm(s, dlci);
1946                 break;
1947
1948         case RFCOMM_FRAME_UIH:
1949                 if (dlci == 0)
1950                         error = ng_btsocket_rfcomm_receive_mcc(s, m0);
1951                 else
1952                         error = ng_btsocket_rfcomm_receive_uih(s, dlci,
1953                                         RFCOMM_PF(hdr->control), m0);
1954
1955                 return (error);
1956                 /* NOT REACHED */
1957
1958         default:
1959                 NG_BTSOCKET_RFCOMM_ERR(
1960 "%s: Invalid RFCOMM packet. Unknown type=%#x\n", __func__, type);
1961                 error = EINVAL;
1962                 break;
1963         }
1964
1965         NG_FREE_M(m0);
1966
1967         return (error);
1968 } /* ng_btsocket_rfcomm_receive_frame */
1969
1970 /*
1971  * Process RFCOMM SABM frame
1972  */
1973
1974 static int
1975 ng_btsocket_rfcomm_receive_sabm(ng_btsocket_rfcomm_session_p s, int dlci)
1976 {
1977         ng_btsocket_rfcomm_pcb_p        pcb = NULL;
1978         int                             error = 0;
1979
1980         mtx_assert(&s->session_mtx, MA_OWNED);
1981
1982         NG_BTSOCKET_RFCOMM_INFO(
1983 "%s: Got SABM, session state=%d, flags=%#x, mtu=%d, dlci=%d\n",
1984                 __func__, s->state, s->flags, s->mtu, dlci);
1985
1986         /* DLCI == 0 means open multiplexor channel */
1987         if (dlci == 0) {
1988                 switch (s->state) {
1989                 case NG_BTSOCKET_RFCOMM_SESSION_CONNECTED:
1990                 case NG_BTSOCKET_RFCOMM_SESSION_OPEN:
1991                         error = ng_btsocket_rfcomm_send_command(s,
1992                                         RFCOMM_FRAME_UA, dlci);
1993                         if (error == 0) {
1994                                 s->state = NG_BTSOCKET_RFCOMM_SESSION_OPEN;
1995                                 ng_btsocket_rfcomm_connect_cfm(s);
1996                         } else {
1997                                 s->state = NG_BTSOCKET_RFCOMM_SESSION_CLOSED;
1998                                 ng_btsocket_rfcomm_session_clean(s);
1999                         }
2000                         break;
2001
2002                 default:
2003                         NG_BTSOCKET_RFCOMM_WARN(
2004 "%s: Got SABM for session in invalid state state=%d, flags=%#x\n",
2005                                 __func__, s->state, s->flags);
2006                         error = EINVAL;
2007                         break;
2008                 }
2009
2010                 return (error);
2011         }
2012
2013         /* Make sure multiplexor channel is open */
2014         if (s->state != NG_BTSOCKET_RFCOMM_SESSION_OPEN) {
2015                 NG_BTSOCKET_RFCOMM_ERR(
2016 "%s: Got SABM for dlci=%d with mulitplexor channel closed, state=%d, " \
2017 "flags=%#x\n",          __func__, dlci, s->state, s->flags);
2018
2019                 return (EINVAL);
2020         }
2021
2022         /*
2023          * Check if we have this DLCI. This might happen when remote
2024          * peer uses PN command before actual open (SABM) happens.
2025          */
2026
2027         pcb = ng_btsocket_rfcomm_pcb_by_dlci(s, dlci);
2028         if (pcb != NULL) {
2029                 mtx_lock(&pcb->pcb_mtx);
2030
2031                 if (pcb->state != NG_BTSOCKET_RFCOMM_DLC_CONNECTING) {
2032                         NG_BTSOCKET_RFCOMM_ERR(
2033 "%s: Got SABM for dlci=%d in invalid state=%d, flags=%#x\n",
2034                                 __func__, dlci, pcb->state, pcb->flags);
2035                         mtx_unlock(&pcb->pcb_mtx);
2036
2037                         return (ENOENT);
2038                 }
2039
2040                 ng_btsocket_rfcomm_untimeout(pcb);
2041
2042                 error = ng_btsocket_rfcomm_send_command(s,RFCOMM_FRAME_UA,dlci);
2043                 if (error == 0)
2044                         error = ng_btsocket_rfcomm_send_msc(pcb);
2045
2046                 if (error == 0) {
2047                         pcb->state = NG_BTSOCKET_RFCOMM_DLC_CONNECTED;
2048                         soisconnected(pcb->so);
2049                 } else
2050                         ng_btsocket_rfcomm_pcb_kill(pcb, error);
2051
2052                 mtx_unlock(&pcb->pcb_mtx);
2053
2054                 return (error);
2055         }
2056
2057         /*
2058          * We do not have requested DLCI, so it must be an incoming connection
2059          * with default parameters. Try to accept it.
2060          */ 
2061
2062         pcb = ng_btsocket_rfcomm_connect_ind(s, RFCOMM_SRVCHANNEL(dlci));
2063         if (pcb != NULL) {
2064                 mtx_lock(&pcb->pcb_mtx);
2065
2066                 pcb->dlci = dlci;
2067
2068                 error = ng_btsocket_rfcomm_send_command(s,RFCOMM_FRAME_UA,dlci);
2069                 if (error == 0)
2070                         error = ng_btsocket_rfcomm_send_msc(pcb);
2071
2072                 if (error == 0) {
2073                         pcb->state = NG_BTSOCKET_RFCOMM_DLC_CONNECTED;
2074                         soisconnected(pcb->so);
2075                 } else
2076                         ng_btsocket_rfcomm_pcb_kill(pcb, error);
2077
2078                 mtx_unlock(&pcb->pcb_mtx);
2079         } else
2080                 /* Nobody is listen()ing on the requested DLCI */
2081                 error = ng_btsocket_rfcomm_send_command(s,RFCOMM_FRAME_DM,dlci);
2082
2083         return (error);
2084 } /* ng_btsocket_rfcomm_receive_sabm */
2085
2086 /*
2087  * Process RFCOMM DISC frame
2088  */
2089
2090 static int
2091 ng_btsocket_rfcomm_receive_disc(ng_btsocket_rfcomm_session_p s, int dlci)
2092 {
2093         ng_btsocket_rfcomm_pcb_p        pcb = NULL;
2094         int                             error = 0;
2095
2096         mtx_assert(&s->session_mtx, MA_OWNED);
2097
2098         NG_BTSOCKET_RFCOMM_INFO(
2099 "%s: Got DISC, session state=%d, flags=%#x, mtu=%d, dlci=%d\n",
2100                 __func__, s->state, s->flags, s->mtu, dlci);
2101
2102         /* DLCI == 0 means close multiplexor channel */
2103         if (dlci == 0) {
2104                 /* XXX FIXME assume that remote side will close the socket */
2105                 error = ng_btsocket_rfcomm_send_command(s, RFCOMM_FRAME_UA, 0);
2106                 if (error == 0) {
2107                         if (s->state == NG_BTSOCKET_RFCOMM_SESSION_DISCONNECTING)
2108                                 s->state = NG_BTSOCKET_RFCOMM_SESSION_CLOSED; /* XXX */
2109                         else
2110                                 s->state = NG_BTSOCKET_RFCOMM_SESSION_DISCONNECTING;
2111                 } else
2112                         s->state = NG_BTSOCKET_RFCOMM_SESSION_CLOSED; /* XXX */
2113
2114                 ng_btsocket_rfcomm_session_clean(s);
2115         } else {
2116                 pcb = ng_btsocket_rfcomm_pcb_by_dlci(s, dlci);
2117                 if (pcb != NULL) {
2118                         int     err;
2119
2120                         mtx_lock(&pcb->pcb_mtx);
2121
2122                         NG_BTSOCKET_RFCOMM_INFO(
2123 "%s: Got DISC for dlci=%d, state=%d, flags=%#x\n",
2124                                 __func__, dlci, pcb->state, pcb->flags);
2125
2126                         error = ng_btsocket_rfcomm_send_command(s,
2127                                         RFCOMM_FRAME_UA, dlci);
2128
2129                         if (pcb->state == NG_BTSOCKET_RFCOMM_DLC_CONNECTED)
2130                                 err = 0;
2131                         else
2132                                 err = ECONNREFUSED;
2133
2134                         ng_btsocket_rfcomm_pcb_kill(pcb, err);
2135
2136                         mtx_unlock(&pcb->pcb_mtx);
2137                 } else {
2138                         NG_BTSOCKET_RFCOMM_WARN(
2139 "%s: Got DISC for non-existing dlci=%d\n", __func__, dlci);
2140
2141                         error = ng_btsocket_rfcomm_send_command(s,
2142                                         RFCOMM_FRAME_DM, dlci);
2143                 }
2144         }
2145
2146         return (error);
2147 } /* ng_btsocket_rfcomm_receive_disc */
2148
2149 /*
2150  * Process RFCOMM UA frame
2151  */
2152
2153 static int
2154 ng_btsocket_rfcomm_receive_ua(ng_btsocket_rfcomm_session_p s, int dlci)
2155 {
2156         ng_btsocket_rfcomm_pcb_p        pcb = NULL;
2157         int                             error = 0;
2158
2159         mtx_assert(&s->session_mtx, MA_OWNED);
2160
2161         NG_BTSOCKET_RFCOMM_INFO(
2162 "%s: Got UA, session state=%d, flags=%#x, mtu=%d, dlci=%d\n",
2163                 __func__, s->state, s->flags, s->mtu, dlci);
2164
2165         /* dlci == 0 means multiplexor channel */
2166         if (dlci == 0) {
2167                 switch (s->state) {
2168                 case NG_BTSOCKET_RFCOMM_SESSION_CONNECTED:
2169                         s->state = NG_BTSOCKET_RFCOMM_SESSION_OPEN;
2170                         ng_btsocket_rfcomm_connect_cfm(s);
2171                         break;
2172
2173                 case NG_BTSOCKET_RFCOMM_SESSION_DISCONNECTING:
2174                         s->state = NG_BTSOCKET_RFCOMM_SESSION_CLOSED;
2175                         ng_btsocket_rfcomm_session_clean(s);
2176                         break;
2177
2178                 default:
2179                         NG_BTSOCKET_RFCOMM_WARN(
2180 "%s: Got UA for session in invalid state=%d(%d), flags=%#x, mtu=%d\n",
2181                                 __func__, s->state, INITIATOR(s), s->flags,
2182                                 s->mtu);
2183                         error = ENOENT;
2184                         break;
2185                 }
2186
2187                 return (error);
2188         }
2189
2190         /* Check if we have this DLCI */
2191         pcb = ng_btsocket_rfcomm_pcb_by_dlci(s, dlci);
2192         if (pcb != NULL) {
2193                 mtx_lock(&pcb->pcb_mtx);
2194
2195                 NG_BTSOCKET_RFCOMM_INFO(
2196 "%s: Got UA for dlci=%d, state=%d, flags=%#x\n",
2197                         __func__, dlci, pcb->state, pcb->flags);
2198
2199                 switch (pcb->state) {
2200                 case NG_BTSOCKET_RFCOMM_DLC_CONNECTING:
2201                         ng_btsocket_rfcomm_untimeout(pcb);
2202
2203                         error = ng_btsocket_rfcomm_send_msc(pcb);
2204                         if (error == 0) {
2205                                 pcb->state = NG_BTSOCKET_RFCOMM_DLC_CONNECTED;
2206                                 soisconnected(pcb->so);
2207                         }
2208                         break;
2209
2210                 case NG_BTSOCKET_RFCOMM_DLC_DISCONNECTING:
2211                         ng_btsocket_rfcomm_pcb_kill(pcb, 0);
2212                         break;
2213
2214                 default:
2215                         NG_BTSOCKET_RFCOMM_WARN(
2216 "%s: Got UA for dlci=%d in invalid state=%d, flags=%#x\n",
2217                                 __func__, dlci, pcb->state, pcb->flags);
2218                         error = ENOENT;
2219                         break;
2220                 }
2221
2222                 mtx_unlock(&pcb->pcb_mtx);
2223         } else {
2224                 NG_BTSOCKET_RFCOMM_WARN(
2225 "%s: Got UA for non-existing dlci=%d\n", __func__, dlci);
2226
2227                 error = ng_btsocket_rfcomm_send_command(s,RFCOMM_FRAME_DM,dlci);
2228         }
2229
2230         return (error);
2231 } /* ng_btsocket_rfcomm_receive_ua */
2232
2233 /*
2234  * Process RFCOMM DM frame
2235  */
2236
2237 static int
2238 ng_btsocket_rfcomm_receive_dm(ng_btsocket_rfcomm_session_p s, int dlci)
2239 {
2240         ng_btsocket_rfcomm_pcb_p        pcb = NULL;
2241         int                             error;
2242
2243         mtx_assert(&s->session_mtx, MA_OWNED);
2244
2245         NG_BTSOCKET_RFCOMM_INFO(
2246 "%s: Got DM, session state=%d, flags=%#x, mtu=%d, dlci=%d\n",
2247                 __func__, s->state, s->flags, s->mtu, dlci);
2248
2249         /* DLCI == 0 means multiplexor channel */
2250         if (dlci == 0) {
2251                 /* Disconnect all dlc's on the session */
2252                 s->state = NG_BTSOCKET_RFCOMM_SESSION_CLOSED;
2253                 ng_btsocket_rfcomm_session_clean(s);
2254         } else {
2255                 pcb = ng_btsocket_rfcomm_pcb_by_dlci(s, dlci);
2256                 if (pcb != NULL) {
2257                         mtx_lock(&pcb->pcb_mtx);
2258
2259                         NG_BTSOCKET_RFCOMM_INFO(
2260 "%s: Got DM for dlci=%d, state=%d, flags=%#x\n",
2261                                 __func__, dlci, pcb->state, pcb->flags);
2262
2263                         if (pcb->state == NG_BTSOCKET_RFCOMM_DLC_CONNECTED)
2264                                 error = ECONNRESET;
2265                         else
2266                                 error = ECONNREFUSED;
2267
2268                         ng_btsocket_rfcomm_pcb_kill(pcb, error);
2269
2270                         mtx_unlock(&pcb->pcb_mtx);
2271                 } else
2272                         NG_BTSOCKET_RFCOMM_WARN(
2273 "%s: Got DM for non-existing dlci=%d\n", __func__, dlci);
2274         }
2275
2276         return (0);
2277 } /* ng_btsocket_rfcomm_receive_dm */
2278
2279 /*
2280  * Process RFCOMM UIH frame (data)
2281  */
2282
2283 static int
2284 ng_btsocket_rfcomm_receive_uih(ng_btsocket_rfcomm_session_p s, int dlci,
2285                 int pf, struct mbuf *m0)
2286 {
2287         ng_btsocket_rfcomm_pcb_p        pcb = NULL;
2288         int                             error = 0;
2289
2290         mtx_assert(&s->session_mtx, MA_OWNED);
2291
2292         NG_BTSOCKET_RFCOMM_INFO(
2293 "%s: Got UIH, session state=%d, flags=%#x, mtu=%d, dlci=%d, pf=%d, len=%d\n",
2294                 __func__, s->state, s->flags, s->mtu, dlci, pf,
2295                 m0->m_pkthdr.len);
2296
2297         /* XXX should we do it here? Check for session flow control */
2298         if (s->flags & NG_BTSOCKET_RFCOMM_SESSION_LFC) {
2299                 NG_BTSOCKET_RFCOMM_WARN(
2300 "%s: Got UIH with session flow control asserted, state=%d, flags=%#x\n",
2301                         __func__, s->state, s->flags);
2302                 goto drop;
2303         }
2304
2305         /* Check if we have this dlci */
2306         pcb = ng_btsocket_rfcomm_pcb_by_dlci(s, dlci);
2307         if (pcb == NULL) {
2308                 NG_BTSOCKET_RFCOMM_WARN(
2309 "%s: Got UIH for non-existing dlci=%d\n", __func__, dlci);
2310                 error = ng_btsocket_rfcomm_send_command(s,RFCOMM_FRAME_DM,dlci);
2311                 goto drop;
2312         }
2313
2314         mtx_lock(&pcb->pcb_mtx);
2315
2316         /* Check dlci state */  
2317         if (pcb->state != NG_BTSOCKET_RFCOMM_DLC_CONNECTED) {
2318                 NG_BTSOCKET_RFCOMM_WARN(
2319 "%s: Got UIH for dlci=%d in invalid state=%d, flags=%#x\n",
2320                         __func__, dlci, pcb->state, pcb->flags);
2321                 error = EINVAL;
2322                 goto drop1;
2323         }
2324
2325         /* Check dlci flow control */
2326         if (((pcb->flags & NG_BTSOCKET_RFCOMM_DLC_CFC) && pcb->rx_cred <= 0) ||
2327              (pcb->lmodem & RFCOMM_MODEM_FC)) {
2328                 NG_BTSOCKET_RFCOMM_ERR(
2329 "%s: Got UIH for dlci=%d with asserted flow control, state=%d, " \
2330 "flags=%#x, rx_cred=%d, lmodem=%#x\n",
2331                         __func__, dlci, pcb->state, pcb->flags,
2332                         pcb->rx_cred, pcb->lmodem);
2333                 goto drop1;
2334         }
2335
2336         /* Did we get any credits? */
2337         if ((pcb->flags & NG_BTSOCKET_RFCOMM_DLC_CFC) && pf) {
2338                 NG_BTSOCKET_RFCOMM_INFO(
2339 "%s: Got %d more credits for dlci=%d, state=%d, flags=%#x, " \
2340 "rx_cred=%d, tx_cred=%d\n",
2341                         __func__, *mtod(m0, u_int8_t *), dlci, pcb->state, 
2342                         pcb->flags, pcb->rx_cred, pcb->tx_cred);
2343
2344                 pcb->tx_cred += *mtod(m0, u_int8_t *);
2345                 m_adj(m0, 1);
2346
2347                 /* Send more from the DLC. XXX check for errors? */
2348                 ng_btsocket_rfcomm_pcb_send(pcb, ALOT);
2349         } 
2350
2351         /* OK the of the rest of the mbuf is the data */
2352         if (m0->m_pkthdr.len > 0) {
2353                 /* If we are using credit flow control decrease rx_cred here */
2354                 if (pcb->flags & NG_BTSOCKET_RFCOMM_DLC_CFC) {
2355                         /* Give remote peer more credits (if needed) */
2356                         if (-- pcb->rx_cred <= RFCOMM_MAX_CREDITS / 2)
2357                                 ng_btsocket_rfcomm_send_credits(pcb);
2358                         else
2359                                 NG_BTSOCKET_RFCOMM_INFO(
2360 "%s: Remote side still has credits, dlci=%d, state=%d, flags=%#x, " \
2361 "rx_cred=%d, tx_cred=%d\n",             __func__, dlci, pcb->state, pcb->flags,
2362                                         pcb->rx_cred, pcb->tx_cred);
2363                 }
2364                 
2365                 /* Check packet against mtu on dlci */
2366                 if (m0->m_pkthdr.len > pcb->mtu) {
2367                         NG_BTSOCKET_RFCOMM_ERR(
2368 "%s: Got oversized UIH for dlci=%d, state=%d, flags=%#x, mtu=%d, len=%d\n",
2369                                 __func__, dlci, pcb->state, pcb->flags,
2370                                 pcb->mtu, m0->m_pkthdr.len);
2371
2372                         error = EMSGSIZE;
2373                 } else if (m0->m_pkthdr.len > sbspace(&pcb->so->so_rcv)) {
2374  
2375                         /*
2376                          * This is really bad. Receive queue on socket does
2377                          * not have enough space for the packet. We do not
2378                          * have any other choice but drop the packet. 
2379                          */
2380  
2381                         NG_BTSOCKET_RFCOMM_ERR(
2382 "%s: Not enough space in socket receive queue. Dropping UIH for dlci=%d, " \
2383 "state=%d, flags=%#x, len=%d, space=%ld\n",
2384                                 __func__, dlci, pcb->state, pcb->flags,
2385                                 m0->m_pkthdr.len, sbspace(&pcb->so->so_rcv));
2386
2387                         error = ENOBUFS;
2388                 } else {
2389                         /* Append packet to the socket receive queue */
2390                         sbappend(&pcb->so->so_rcv, m0);
2391                         m0 = NULL;
2392
2393                         sorwakeup(pcb->so);
2394                 }
2395         }
2396 drop1:
2397         mtx_unlock(&pcb->pcb_mtx);
2398 drop:
2399         NG_FREE_M(m0); /* checks for != NULL */
2400
2401         return (error);
2402 } /* ng_btsocket_rfcomm_receive_uih */
2403
2404 /*
2405  * Process RFCOMM MCC command (Multiplexor)
2406  * 
2407  * From TS 07.10 spec
2408  *
2409  * "5.4.3.1 Information Data
2410  * 
2411  *  ...The frames (UIH) sent by the initiating station have the C/R bit set 
2412  *  to 1 and those sent by the responding station have the C/R bit set to 0..."
2413  *
2414  * "5.4.6.2 Operating procedures
2415  *
2416  *  Messages always exist in pairs; a command message and a corresponding 
2417  *  response message. If the C/R bit is set to 1 the message is a command, 
2418  *  if it is set to 0 the message is a response...
2419  *
2420  *  ...
2421  * 
2422  *  NOTE: Notice that when UIH frames are used to convey information on DLCI 0
2423  *  there are at least two different fields that contain a C/R bit, and the 
2424  *  bits are set of different form. The C/R bit in the Type field shall be set
2425  *  as it is stated above, while the C/R bit in the Address field (see subclause
2426  *  5.2.1.2) shall be set as it is described in subclause 5.4.3.1."
2427  */
2428
2429 static int
2430 ng_btsocket_rfcomm_receive_mcc(ng_btsocket_rfcomm_session_p s, struct mbuf *m0)
2431 {
2432         struct rfcomm_mcc_hdr   *hdr = NULL;
2433         u_int8_t                 cr, type, length;
2434
2435         mtx_assert(&s->session_mtx, MA_OWNED);
2436
2437         /*
2438          * We can access data directly in the first mbuf, because we have
2439          * m_pullup()'ed mbuf chain in ng_btsocket_rfcomm_receive_frame().
2440          * All MCC commands should fit into single mbuf (except probably TEST).
2441          */
2442
2443         hdr = mtod(m0, struct rfcomm_mcc_hdr *);
2444         cr = RFCOMM_CR(hdr->type);
2445         type = RFCOMM_MCC_TYPE(hdr->type);
2446         length = RFCOMM_MCC_LENGTH(hdr->length);
2447
2448         /* Check MCC frame length */
2449         if (sizeof(*hdr) + length != m0->m_pkthdr.len) {
2450                 NG_BTSOCKET_RFCOMM_ERR(
2451 "%s: Invalid MCC frame length=%d, len=%d\n",
2452                         __func__, length, m0->m_pkthdr.len);
2453                 NG_FREE_M(m0);
2454
2455                 return (EMSGSIZE);
2456         }
2457
2458         switch (type) {
2459         case RFCOMM_MCC_TEST:
2460                 return (ng_btsocket_rfcomm_receive_test(s, m0));
2461                 /* NOT REACHED */
2462
2463         case RFCOMM_MCC_FCON:
2464         case RFCOMM_MCC_FCOFF:
2465                 return (ng_btsocket_rfcomm_receive_fc(s, m0));
2466                 /* NOT REACHED */
2467
2468         case RFCOMM_MCC_MSC:
2469                 return (ng_btsocket_rfcomm_receive_msc(s, m0));
2470                 /* NOT REACHED */
2471
2472         case RFCOMM_MCC_RPN:
2473                 return (ng_btsocket_rfcomm_receive_rpn(s, m0));
2474                 /* NOT REACHED */
2475
2476         case RFCOMM_MCC_RLS:
2477                 return (ng_btsocket_rfcomm_receive_rls(s, m0));
2478                 /* NOT REACHED */
2479
2480         case RFCOMM_MCC_PN:
2481                 return (ng_btsocket_rfcomm_receive_pn(s, m0));
2482                 /* NOT REACHED */
2483
2484         case RFCOMM_MCC_NSC:
2485                 NG_BTSOCKET_RFCOMM_ERR(
2486 "%s: Got MCC NSC, type=%#x, cr=%d, length=%d, session state=%d, flags=%#x, " \
2487 "mtu=%d, len=%d\n",     __func__, RFCOMM_MCC_TYPE(*((u_int8_t *)(hdr + 1))), cr,
2488                          length, s->state, s->flags, s->mtu, m0->m_pkthdr.len);
2489                 NG_FREE_M(m0);
2490                 break;
2491
2492         default:
2493                 NG_BTSOCKET_RFCOMM_ERR(
2494 "%s: Got unknown MCC, type=%#x, cr=%d, length=%d, session state=%d, " \
2495 "flags=%#x, mtu=%d, len=%d\n",
2496                         __func__, type, cr, length, s->state, s->flags,
2497                         s->mtu, m0->m_pkthdr.len);
2498
2499                 /* Reuse mbuf to send NSC */
2500                 hdr = mtod(m0, struct rfcomm_mcc_hdr *);
2501                 m0->m_pkthdr.len = m0->m_len = sizeof(*hdr);
2502
2503                 /* Create MCC NSC header */
2504                 hdr->type = RFCOMM_MKMCC_TYPE(0, RFCOMM_MCC_NSC);
2505                 hdr->length = RFCOMM_MKLEN8(1);
2506
2507                 /* Put back MCC command type we did not like */
2508                 m0->m_data[m0->m_len] = RFCOMM_MKMCC_TYPE(cr, type);
2509                 m0->m_pkthdr.len ++;
2510                 m0->m_len ++;
2511
2512                 /* Send UIH frame */
2513                 return (ng_btsocket_rfcomm_send_uih(s,
2514                                 RFCOMM_MKADDRESS(INITIATOR(s), 0), 0, 0, m0));
2515                 /* NOT REACHED */
2516         }
2517
2518         return (0);
2519 } /* ng_btsocket_rfcomm_receive_mcc */
2520
2521 /*
2522  * Receive RFCOMM TEST MCC command
2523  */
2524
2525 static int
2526 ng_btsocket_rfcomm_receive_test(ng_btsocket_rfcomm_session_p s, struct mbuf *m0)
2527 {
2528         struct rfcomm_mcc_hdr   *hdr = mtod(m0, struct rfcomm_mcc_hdr *);
2529         int                      error = 0;
2530
2531         mtx_assert(&s->session_mtx, MA_OWNED);
2532
2533         NG_BTSOCKET_RFCOMM_INFO(
2534 "%s: Got MCC TEST, cr=%d, length=%d, session state=%d, flags=%#x, mtu=%d, " \
2535 "len=%d\n",     __func__, RFCOMM_CR(hdr->type), RFCOMM_MCC_LENGTH(hdr->length),
2536                 s->state, s->flags, s->mtu, m0->m_pkthdr.len);
2537
2538         if (RFCOMM_CR(hdr->type)) {
2539                 hdr->type = RFCOMM_MKMCC_TYPE(0, RFCOMM_MCC_TEST);
2540                 error = ng_btsocket_rfcomm_send_uih(s,
2541                                 RFCOMM_MKADDRESS(INITIATOR(s), 0), 0, 0, m0);
2542         } else
2543                 NG_FREE_M(m0); /* XXX ignore response */
2544
2545         return (error);
2546 } /* ng_btsocket_rfcomm_receive_test */
2547
2548 /*
2549  * Receive RFCOMM FCON/FCOFF MCC command
2550  */
2551
2552 static int
2553 ng_btsocket_rfcomm_receive_fc(ng_btsocket_rfcomm_session_p s, struct mbuf *m0)
2554 {
2555         struct rfcomm_mcc_hdr   *hdr = mtod(m0, struct rfcomm_mcc_hdr *);
2556         u_int8_t                 type = RFCOMM_MCC_TYPE(hdr->type);
2557         int                      error = 0;
2558
2559         mtx_assert(&s->session_mtx, MA_OWNED);
2560
2561         /*
2562          * Turn ON/OFF aggregate flow on the entire session. When remote peer 
2563          * asserted flow control no transmission shall occur except on dlci 0
2564          * (control channel).
2565          */
2566
2567         NG_BTSOCKET_RFCOMM_INFO(
2568 "%s: Got MCC FC%s, cr=%d, length=%d, session state=%d, flags=%#x, mtu=%d, " \
2569 "len=%d\n",     __func__, (type == RFCOMM_MCC_FCON)? "ON" : "OFF",
2570                 RFCOMM_CR(hdr->type), RFCOMM_MCC_LENGTH(hdr->length),
2571                 s->state, s->flags, s->mtu, m0->m_pkthdr.len);
2572
2573         if (RFCOMM_CR(hdr->type)) {
2574                 if (type == RFCOMM_MCC_FCON)
2575                         s->flags &= ~NG_BTSOCKET_RFCOMM_SESSION_RFC;
2576                 else
2577                         s->flags |= NG_BTSOCKET_RFCOMM_SESSION_RFC;
2578
2579                 hdr->type = RFCOMM_MKMCC_TYPE(0, type);
2580                 error = ng_btsocket_rfcomm_send_uih(s,
2581                                 RFCOMM_MKADDRESS(INITIATOR(s), 0), 0, 0, m0);
2582         } else
2583                 NG_FREE_M(m0); /* XXX ignore response */
2584
2585         return (error);
2586 } /* ng_btsocket_rfcomm_receive_fc  */
2587
2588 /*
2589  * Receive RFCOMM MSC MCC command
2590  */
2591
2592 static int
2593 ng_btsocket_rfcomm_receive_msc(ng_btsocket_rfcomm_session_p s, struct mbuf *m0)
2594 {
2595         struct rfcomm_mcc_hdr           *hdr = mtod(m0, struct rfcomm_mcc_hdr*);
2596         struct rfcomm_mcc_msc           *msc = (struct rfcomm_mcc_msc *)(hdr+1);
2597         ng_btsocket_rfcomm_pcb_t        *pcb = NULL;
2598         int                              error = 0;
2599
2600         mtx_assert(&s->session_mtx, MA_OWNED);
2601
2602         NG_BTSOCKET_RFCOMM_INFO(
2603 "%s: Got MCC MSC, dlci=%d, cr=%d, length=%d, session state=%d, flags=%#x, " \
2604 "mtu=%d, len=%d\n",
2605                 __func__,  RFCOMM_DLCI(msc->address), RFCOMM_CR(hdr->type),
2606                 RFCOMM_MCC_LENGTH(hdr->length), s->state, s->flags,
2607                 s->mtu, m0->m_pkthdr.len);
2608
2609         if (RFCOMM_CR(hdr->type)) {
2610                 pcb = ng_btsocket_rfcomm_pcb_by_dlci(s, RFCOMM_DLCI(msc->address));
2611                 if (pcb == NULL) {
2612                         NG_BTSOCKET_RFCOMM_WARN(
2613 "%s: Got MSC command for non-existing dlci=%d\n",
2614                                 __func__, RFCOMM_DLCI(msc->address));
2615                         NG_FREE_M(m0);
2616
2617                         return (ENOENT);
2618                 }
2619
2620                 mtx_lock(&pcb->pcb_mtx);
2621
2622                 if (pcb->state != NG_BTSOCKET_RFCOMM_DLC_CONNECTING &&
2623                     pcb->state != NG_BTSOCKET_RFCOMM_DLC_CONNECTED) {
2624                         NG_BTSOCKET_RFCOMM_WARN(
2625 "%s: Got MSC on dlci=%d in invalid state=%d\n",
2626                                 __func__, RFCOMM_DLCI(msc->address),
2627                                 pcb->state);
2628
2629                         mtx_unlock(&pcb->pcb_mtx);
2630                         NG_FREE_M(m0);
2631
2632                         return (EINVAL);
2633                 }
2634
2635                 pcb->rmodem = msc->modem; /* Update remote port signals */
2636
2637                 hdr->type = RFCOMM_MKMCC_TYPE(0, RFCOMM_MCC_MSC);
2638                 error = ng_btsocket_rfcomm_send_uih(s,
2639                                 RFCOMM_MKADDRESS(INITIATOR(s), 0), 0, 0, m0);
2640
2641 #if 0 /* YYY */
2642                 /* Send more data from DLC. XXX check for errors? */
2643                 if (!(pcb->rmodem & RFCOMM_MODEM_FC) &&
2644                     !(pcb->flags & NG_BTSOCKET_RFCOMM_DLC_CFC))
2645                         ng_btsocket_rfcomm_pcb_send(pcb, ALOT);
2646 #endif /* YYY */
2647
2648                 mtx_unlock(&pcb->pcb_mtx);
2649         } else
2650                 NG_FREE_M(m0); /* XXX ignore response */
2651
2652         return (error);
2653 } /* ng_btsocket_rfcomm_receive_msc */
2654
2655 /*
2656  * Receive RFCOMM RPN MCC command
2657  * XXX FIXME do we need htole16/le16toh for RPN param_mask?
2658  */
2659
2660 static int
2661 ng_btsocket_rfcomm_receive_rpn(ng_btsocket_rfcomm_session_p s, struct mbuf *m0)
2662 {
2663         struct rfcomm_mcc_hdr   *hdr = mtod(m0, struct rfcomm_mcc_hdr *);
2664         struct rfcomm_mcc_rpn   *rpn = (struct rfcomm_mcc_rpn *)(hdr + 1);
2665         int                      error = 0;
2666         u_int16_t                param_mask;
2667         u_int8_t                 bit_rate, data_bits, stop_bits, parity,
2668                                  flow_control, xon_char, xoff_char;
2669
2670         mtx_assert(&s->session_mtx, MA_OWNED);
2671
2672         NG_BTSOCKET_RFCOMM_INFO(
2673 "%s: Got MCC RPN, dlci=%d, cr=%d, length=%d, session state=%d, flags=%#x, " \
2674 "mtu=%d, len=%d\n",
2675                 __func__, RFCOMM_DLCI(rpn->dlci), RFCOMM_CR(hdr->type),
2676                 RFCOMM_MCC_LENGTH(hdr->length), s->state, s->flags,
2677                 s->mtu, m0->m_pkthdr.len);
2678
2679         if (RFCOMM_CR(hdr->type)) {
2680                 param_mask = RFCOMM_RPN_PM_ALL;
2681
2682                 if (RFCOMM_MCC_LENGTH(hdr->length) == 1) {
2683                         /* Request - return default setting */
2684                         bit_rate = RFCOMM_RPN_BR_115200;
2685                         data_bits = RFCOMM_RPN_DATA_8;
2686                         stop_bits = RFCOMM_RPN_STOP_1;
2687                         parity = RFCOMM_RPN_PARITY_NONE;
2688                         flow_control = RFCOMM_RPN_FLOW_NONE;
2689                         xon_char = RFCOMM_RPN_XON_CHAR;
2690                         xoff_char = RFCOMM_RPN_XOFF_CHAR;
2691                 } else {
2692                         /*
2693                          * Ignore/accept bit_rate, 8 bits, 1 stop bit, no 
2694                          * parity, no flow control lines, default XON/XOFF 
2695                          * chars.
2696                          */
2697
2698                         bit_rate = rpn->bit_rate;
2699                         rpn->param_mask = le16toh(rpn->param_mask); /* XXX */
2700
2701                         data_bits = RFCOMM_RPN_DATA_BITS(rpn->line_settings);
2702                         if (rpn->param_mask & RFCOMM_RPN_PM_DATA &&
2703                             data_bits != RFCOMM_RPN_DATA_8) {
2704                                 data_bits = RFCOMM_RPN_DATA_8;
2705                                 param_mask ^= RFCOMM_RPN_PM_DATA;
2706                         }
2707
2708                         stop_bits = RFCOMM_RPN_STOP_BITS(rpn->line_settings);
2709                         if (rpn->param_mask & RFCOMM_RPN_PM_STOP &&
2710                             stop_bits != RFCOMM_RPN_STOP_1) {
2711                                 stop_bits = RFCOMM_RPN_STOP_1;
2712                                 param_mask ^= RFCOMM_RPN_PM_STOP;
2713                         }
2714
2715                         parity = RFCOMM_RPN_PARITY(rpn->line_settings);
2716                         if (rpn->param_mask & RFCOMM_RPN_PM_PARITY &&
2717                             parity != RFCOMM_RPN_PARITY_NONE) {
2718                                 parity = RFCOMM_RPN_PARITY_NONE;
2719                                 param_mask ^= RFCOMM_RPN_PM_PARITY;
2720                         }
2721
2722                         flow_control = rpn->flow_control;
2723                         if (rpn->param_mask & RFCOMM_RPN_PM_FLOW &&
2724                             flow_control != RFCOMM_RPN_FLOW_NONE) {
2725                                 flow_control = RFCOMM_RPN_FLOW_NONE;
2726                                 param_mask ^= RFCOMM_RPN_PM_FLOW;
2727                         }
2728
2729                         xon_char = rpn->xon_char;
2730                         if (rpn->param_mask & RFCOMM_RPN_PM_XON &&
2731                             xon_char != RFCOMM_RPN_XON_CHAR) {
2732                                 xon_char = RFCOMM_RPN_XON_CHAR;
2733                                 param_mask ^= RFCOMM_RPN_PM_XON;
2734                         }
2735
2736                         xoff_char = rpn->xoff_char;
2737                         if (rpn->param_mask & RFCOMM_RPN_PM_XOFF &&
2738                             xoff_char != RFCOMM_RPN_XOFF_CHAR) {
2739                                 xoff_char = RFCOMM_RPN_XOFF_CHAR;
2740                                 param_mask ^= RFCOMM_RPN_PM_XOFF;
2741                         }
2742                 }
2743
2744                 rpn->bit_rate = bit_rate;
2745                 rpn->line_settings = RFCOMM_MKRPN_LINE_SETTINGS(data_bits, 
2746                                                 stop_bits, parity);
2747                 rpn->flow_control = flow_control;
2748                 rpn->xon_char = xon_char;
2749                 rpn->xoff_char = xoff_char;
2750                 rpn->param_mask = htole16(param_mask); /* XXX */
2751
2752                 m0->m_pkthdr.len = m0->m_len = sizeof(*hdr) + sizeof(*rpn);
2753
2754                 hdr->type = RFCOMM_MKMCC_TYPE(0, RFCOMM_MCC_RPN);
2755                 error = ng_btsocket_rfcomm_send_uih(s,
2756                                 RFCOMM_MKADDRESS(INITIATOR(s), 0), 0, 0, m0);
2757         } else
2758                 NG_FREE_M(m0); /* XXX ignore response */
2759
2760         return (error);
2761 } /* ng_btsocket_rfcomm_receive_rpn */
2762
2763 /*
2764  * Receive RFCOMM RLS MCC command
2765  */
2766
2767 static int
2768 ng_btsocket_rfcomm_receive_rls(ng_btsocket_rfcomm_session_p s, struct mbuf *m0)
2769 {
2770         struct rfcomm_mcc_hdr   *hdr = mtod(m0, struct rfcomm_mcc_hdr *);
2771         struct rfcomm_mcc_rls   *rls = (struct rfcomm_mcc_rls *)(hdr + 1);
2772         int                      error = 0;
2773
2774         mtx_assert(&s->session_mtx, MA_OWNED);
2775
2776         /*
2777          * XXX FIXME Do we have to do anything else here? Remote peer tries to 
2778          * tell us something about DLCI. Just report what we have received and
2779          * return back received values as required by TS 07.10 spec.
2780          */
2781
2782         NG_BTSOCKET_RFCOMM_INFO(
2783 "%s: Got MCC RLS, dlci=%d, status=%#x, cr=%d, length=%d, session state=%d, " \
2784 "flags=%#x, mtu=%d, len=%d\n",
2785                 __func__, RFCOMM_DLCI(rls->address), rls->status,
2786                 RFCOMM_CR(hdr->type), RFCOMM_MCC_LENGTH(hdr->length),
2787                 s->state, s->flags, s->mtu, m0->m_pkthdr.len);
2788
2789         if (RFCOMM_CR(hdr->type)) {
2790                 if (rls->status & 0x1)
2791                         NG_BTSOCKET_RFCOMM_ERR(
2792 "%s: Got RLS dlci=%d, error=%#x\n", __func__, RFCOMM_DLCI(rls->address),
2793                                 rls->status >> 1);
2794
2795                 hdr->type = RFCOMM_MKMCC_TYPE(0, RFCOMM_MCC_RLS);
2796                 error = ng_btsocket_rfcomm_send_uih(s,
2797                                 RFCOMM_MKADDRESS(INITIATOR(s), 0), 0, 0, m0);
2798         } else
2799                 NG_FREE_M(m0); /* XXX ignore responses */
2800
2801         return (error);
2802 } /* ng_btsocket_rfcomm_receive_rls */
2803
2804 /*
2805  * Receive RFCOMM PN MCC command
2806  */
2807
2808 static int
2809 ng_btsocket_rfcomm_receive_pn(ng_btsocket_rfcomm_session_p s, struct mbuf *m0)
2810 {
2811         struct rfcomm_mcc_hdr           *hdr = mtod(m0, struct rfcomm_mcc_hdr*);
2812         struct rfcomm_mcc_pn            *pn = (struct rfcomm_mcc_pn *)(hdr+1);
2813         ng_btsocket_rfcomm_pcb_t        *pcb = NULL;
2814         int                              error = 0;
2815
2816         mtx_assert(&s->session_mtx, MA_OWNED);
2817
2818         NG_BTSOCKET_RFCOMM_INFO(
2819 "%s: Got MCC PN, dlci=%d, cr=%d, length=%d, flow_control=%#x, priority=%d, " \
2820 "ack_timer=%d, mtu=%d, max_retrans=%d, credits=%d, session state=%d, " \
2821 "flags=%#x, session mtu=%d, len=%d\n",
2822                 __func__, pn->dlci, RFCOMM_CR(hdr->type),
2823                 RFCOMM_MCC_LENGTH(hdr->length), pn->flow_control, pn->priority,
2824                 pn->ack_timer, le16toh(pn->mtu), pn->max_retrans, pn->credits,
2825                 s->state, s->flags, s->mtu, m0->m_pkthdr.len);
2826
2827         if (pn->dlci == 0) {
2828                 NG_BTSOCKET_RFCOMM_ERR("%s: Zero dlci in MCC PN\n", __func__);
2829                 NG_FREE_M(m0);
2830
2831                 return (EINVAL);
2832         }
2833
2834         /* Check if we have this dlci */
2835         pcb = ng_btsocket_rfcomm_pcb_by_dlci(s, pn->dlci);
2836         if (pcb != NULL) {
2837                 mtx_lock(&pcb->pcb_mtx);
2838
2839                 if (RFCOMM_CR(hdr->type)) {
2840                         /* PN Request */
2841                         ng_btsocket_rfcomm_set_pn(pcb, 1, pn->flow_control,
2842                                 pn->credits, pn->mtu);
2843
2844                         if (pcb->flags & NG_BTSOCKET_RFCOMM_DLC_CFC) {
2845                                 pn->flow_control = 0xe0;
2846                                 pn->credits = RFCOMM_DEFAULT_CREDITS;
2847                         } else {
2848                                 pn->flow_control = 0;
2849                                 pn->credits = 0;
2850                         }
2851
2852                         hdr->type = RFCOMM_MKMCC_TYPE(0, RFCOMM_MCC_PN);
2853                         error = ng_btsocket_rfcomm_send_uih(s, 
2854                                         RFCOMM_MKADDRESS(INITIATOR(s), 0),
2855                                         0, 0, m0);
2856                 } else {
2857                         /* PN Response - proceed with SABM. Timeout still set */
2858                         if (pcb->state == NG_BTSOCKET_RFCOMM_DLC_CONFIGURING) {
2859                                 ng_btsocket_rfcomm_set_pn(pcb, 0,
2860                                         pn->flow_control, pn->credits, pn->mtu);
2861
2862                                 pcb->state = NG_BTSOCKET_RFCOMM_DLC_CONNECTING;
2863                                 error = ng_btsocket_rfcomm_send_command(s,
2864                                                 RFCOMM_FRAME_SABM, pn->dlci);
2865                         } else
2866                                 NG_BTSOCKET_RFCOMM_WARN(
2867 "%s: Got PN response for dlci=%d in invalid state=%d\n",
2868                                         __func__, pn->dlci, pcb->state);
2869
2870                         NG_FREE_M(m0);
2871                 }
2872
2873                 mtx_unlock(&pcb->pcb_mtx);
2874         } else if (RFCOMM_CR(hdr->type)) {
2875                 /* PN request to non-existing dlci - incomming connection */
2876                 pcb = ng_btsocket_rfcomm_connect_ind(s,
2877                                 RFCOMM_SRVCHANNEL(pn->dlci));
2878                 if (pcb != NULL) {
2879                         mtx_lock(&pcb->pcb_mtx);
2880
2881                         pcb->dlci = pn->dlci;
2882
2883                         ng_btsocket_rfcomm_set_pn(pcb, 1, pn->flow_control,
2884                                 pn->credits, pn->mtu);
2885
2886                         if (pcb->flags & NG_BTSOCKET_RFCOMM_DLC_CFC) {
2887                                 pn->flow_control = 0xe0;
2888                                 pn->credits = RFCOMM_DEFAULT_CREDITS;
2889                         } else {
2890                                 pn->flow_control = 0;
2891                                 pn->credits = 0;
2892                         }
2893
2894                         hdr->type = RFCOMM_MKMCC_TYPE(0, RFCOMM_MCC_PN);
2895                         error = ng_btsocket_rfcomm_send_uih(s, 
2896                                         RFCOMM_MKADDRESS(INITIATOR(s), 0),
2897                                         0, 0, m0);
2898
2899                         if (error == 0) {
2900                                 ng_btsocket_rfcomm_timeout(pcb);
2901                                 pcb->state = NG_BTSOCKET_RFCOMM_DLC_CONNECTING;
2902                                 soisconnecting(pcb->so);
2903                         } else
2904                                 ng_btsocket_rfcomm_pcb_kill(pcb, error);
2905
2906                         mtx_unlock(&pcb->pcb_mtx);
2907                 } else {
2908                         /* Nobody is listen()ing on this channel */
2909                         error = ng_btsocket_rfcomm_send_command(s,
2910                                         RFCOMM_FRAME_DM, pn->dlci);
2911                         NG_FREE_M(m0);
2912                 }
2913         } else
2914                 NG_FREE_M(m0); /* XXX ignore response to non-existing dlci */
2915
2916         return (error);
2917 } /* ng_btsocket_rfcomm_receive_pn */
2918
2919 /*
2920  * Set PN parameters for dlci. Caller must hold pcb->pcb_mtx.
2921  * 
2922  * From Bluetooth spec.
2923  * 
2924  * "... The CL1 - CL4 field is completely redefined. (In TS07.10 this defines 
2925  *  the convergence layer to use, which is not applicable to RFCOMM. In RFCOMM,
2926  *  in Bluetooth versions up to 1.0B, this field was forced to 0).
2927  *
2928  *  In the PN request sent prior to a DLC establishment, this field must contain
2929  *  the value 15 (0xF), indicating support of credit based flow control in the 
2930  *  sender. See Table 5.3 below. If the PN response contains any other value 
2931  *  than 14 (0xE) in this field, it is inferred that the peer RFCOMM entity is 
2932  *  not supporting the credit based flow control feature. (This is only possible
2933  *  if the peer RFCOMM implementation is only conforming to Bluetooth version 
2934  *  1.0B.) If a PN request is sent on an already open DLC, then this field must
2935  *  contain the value zero; it is not possible to set initial credits  more 
2936  *  than once per DLC activation. A responding implementation must set this 
2937  *  field in the PN response to 14 (0xE), if (and only if) the value in the PN 
2938  *  request was 15..."
2939  */
2940
2941 static void
2942 ng_btsocket_rfcomm_set_pn(ng_btsocket_rfcomm_pcb_p pcb, u_int8_t cr,
2943                 u_int8_t flow_control, u_int8_t credits, u_int16_t mtu)
2944 {
2945         mtx_assert(&pcb->pcb_mtx, MA_OWNED);
2946
2947         pcb->mtu = le16toh(mtu);
2948
2949         if (cr) {
2950                 if (flow_control == 0xf0) {
2951                         pcb->flags |= NG_BTSOCKET_RFCOMM_DLC_CFC;
2952                         pcb->tx_cred = credits;
2953                 } else {
2954                         pcb->flags &= ~NG_BTSOCKET_RFCOMM_DLC_CFC;
2955                         pcb->tx_cred = 0;
2956                 }
2957         } else {
2958                 if (flow_control == 0xe0) {
2959                         pcb->flags |= NG_BTSOCKET_RFCOMM_DLC_CFC;
2960                         pcb->tx_cred = credits;
2961                 } else {
2962                         pcb->flags &= ~NG_BTSOCKET_RFCOMM_DLC_CFC;
2963                         pcb->tx_cred = 0;
2964                 }
2965         }
2966
2967         NG_BTSOCKET_RFCOMM_INFO(
2968 "%s: cr=%d, dlci=%d, state=%d, flags=%#x, mtu=%d, rx_cred=%d, tx_cred=%d\n",
2969                 __func__, cr, pcb->dlci, pcb->state, pcb->flags, pcb->mtu,
2970                 pcb->rx_cred, pcb->tx_cred);
2971 } /* ng_btsocket_rfcomm_set_pn */
2972
2973 /*
2974  * Send RFCOMM SABM/DISC/UA/DM frames. Caller must hold s->session_mtx
2975  */
2976
2977 static int
2978 ng_btsocket_rfcomm_send_command(ng_btsocket_rfcomm_session_p s,
2979                 u_int8_t type, u_int8_t dlci)
2980 {
2981         struct rfcomm_cmd_hdr   *hdr = NULL;
2982         struct mbuf             *m = NULL;
2983         int                      cr;
2984
2985         mtx_assert(&s->session_mtx, MA_OWNED);
2986
2987         NG_BTSOCKET_RFCOMM_INFO(
2988 "%s: Sending command type %#x, session state=%d, flags=%#x, mtu=%d, dlci=%d\n",
2989                 __func__, type, s->state, s->flags, s->mtu, dlci);
2990
2991         switch (type) {
2992         case RFCOMM_FRAME_SABM:
2993         case RFCOMM_FRAME_DISC:
2994                 cr = INITIATOR(s);
2995                 break;
2996
2997         case RFCOMM_FRAME_UA:
2998         case RFCOMM_FRAME_DM:
2999                 cr = !INITIATOR(s);
3000                 break;
3001
3002         default:
3003                 panic("%s: Invalid frame type=%#x\n", __func__, type);
3004                 return (EINVAL);
3005                 /* NOT REACHED */
3006         }
3007
3008         MGETHDR(m, MB_DONTWAIT, MT_DATA);
3009         if (m == NULL)
3010                 return (ENOBUFS);
3011
3012         m->m_pkthdr.len = m->m_len = sizeof(*hdr);
3013
3014         hdr = mtod(m, struct rfcomm_cmd_hdr *);
3015         hdr->address = RFCOMM_MKADDRESS(cr, dlci);
3016         hdr->control = RFCOMM_MKCONTROL(type, 1);
3017         hdr->length = RFCOMM_MKLEN8(0);
3018         hdr->fcs = ng_btsocket_rfcomm_fcs3((u_int8_t *) hdr);
3019
3020         NG_BT_MBUFQ_ENQUEUE(&s->outq, m);
3021
3022         return (0);
3023 } /* ng_btsocket_rfcomm_send_command */
3024
3025 /*
3026  * Send RFCOMM UIH frame. Caller must hold s->session_mtx
3027  */
3028
3029 static int
3030 ng_btsocket_rfcomm_send_uih(ng_btsocket_rfcomm_session_p s, u_int8_t address,
3031                 u_int8_t pf, u_int8_t credits, struct mbuf *data)
3032 {
3033         struct rfcomm_frame_hdr *hdr = NULL;
3034         struct mbuf             *m = NULL, *mcrc = NULL;
3035         u_int16_t                length;
3036
3037         mtx_assert(&s->session_mtx, MA_OWNED);
3038
3039         MGETHDR(m, MB_DONTWAIT, MT_DATA);
3040         if (m == NULL) {
3041                 NG_FREE_M(data);
3042                 return (ENOBUFS);
3043         }
3044         m->m_pkthdr.len = m->m_len = sizeof(*hdr);
3045
3046         MGET(mcrc, MB_DONTWAIT, MT_DATA);
3047         if (mcrc == NULL) {
3048                 NG_FREE_M(data);
3049                 return (ENOBUFS);
3050         }
3051         mcrc->m_len = 1;
3052
3053         /* Fill UIH frame header */
3054         hdr = mtod(m, struct rfcomm_frame_hdr *);
3055         hdr->address = address;
3056         hdr->control = RFCOMM_MKCONTROL(RFCOMM_FRAME_UIH, pf);
3057
3058         /* Calculate FCS */
3059         mcrc->m_data[0] = ng_btsocket_rfcomm_fcs2((u_int8_t *) hdr);
3060
3061         /* Put length back */
3062         length = (data != NULL)? data->m_pkthdr.len : 0;
3063         if (length > 127) {
3064                 u_int16_t       l = htole16(RFCOMM_MKLEN16(length));
3065
3066                 bcopy(&l, &hdr->length, sizeof(l));
3067                 m->m_pkthdr.len ++;
3068                 m->m_len ++;
3069         } else
3070                 hdr->length = RFCOMM_MKLEN8(length);
3071
3072         if (pf) {
3073                 m->m_data[m->m_len] = credits;
3074                 m->m_pkthdr.len ++;
3075                 m->m_len ++;
3076         }
3077
3078         /* Add payload */
3079         if (data != NULL) {
3080                 m_cat(m, data);
3081                 m->m_pkthdr.len += length;
3082         }
3083
3084         /* Put FCS back */
3085         m_cat(m, mcrc);
3086         m->m_pkthdr.len ++;
3087
3088         NG_BTSOCKET_RFCOMM_INFO(
3089 "%s: Sending UIH state=%d, flags=%#x, address=%d, length=%d, pf=%d, " \
3090 "credits=%d, len=%d\n",
3091                 __func__, s->state, s->flags, address, length, pf, credits,
3092                 m->m_pkthdr.len);
3093
3094         NG_BT_MBUFQ_ENQUEUE(&s->outq, m);
3095
3096         return (0);
3097 } /* ng_btsocket_rfcomm_send_uih */
3098
3099 /*
3100  * Send MSC request. Caller must hold pcb->pcb_mtx and pcb->session->session_mtx
3101  */
3102
3103 static int
3104 ng_btsocket_rfcomm_send_msc(ng_btsocket_rfcomm_pcb_p pcb)
3105 {
3106         struct mbuf             *m = NULL;
3107         struct rfcomm_mcc_hdr   *hdr = NULL;
3108         struct rfcomm_mcc_msc   *msc = NULL;
3109
3110         mtx_assert(&pcb->session->session_mtx, MA_OWNED);
3111         mtx_assert(&pcb->pcb_mtx, MA_OWNED);
3112
3113         MGETHDR(m, MB_DONTWAIT, MT_DATA);
3114         if (m == NULL)
3115                 return (ENOBUFS);
3116
3117         m->m_pkthdr.len = m->m_len = sizeof(*hdr) + sizeof(*msc);
3118
3119         hdr = mtod(m, struct rfcomm_mcc_hdr *);
3120         msc = (struct rfcomm_mcc_msc *)(hdr + 1);
3121
3122         hdr->type = RFCOMM_MKMCC_TYPE(1, RFCOMM_MCC_MSC);
3123         hdr->length = RFCOMM_MKLEN8(sizeof(*msc));
3124
3125         msc->address = RFCOMM_MKADDRESS(1, pcb->dlci);
3126         msc->modem = pcb->lmodem;
3127
3128         NG_BTSOCKET_RFCOMM_INFO(
3129 "%s: Sending MSC dlci=%d, state=%d, flags=%#x, address=%d, modem=%#x\n",
3130                 __func__, pcb->dlci, pcb->state, pcb->flags, msc->address,
3131                 msc->modem);
3132
3133         return (ng_btsocket_rfcomm_send_uih(pcb->session,
3134                         RFCOMM_MKADDRESS(INITIATOR(pcb->session), 0), 0, 0, m));
3135 } /* ng_btsocket_rfcomm_send_msc */
3136
3137 /*
3138  * Send PN request. Caller must hold pcb->pcb_mtx and pcb->session->session_mtx
3139  */
3140
3141 static int
3142 ng_btsocket_rfcomm_send_pn(ng_btsocket_rfcomm_pcb_p pcb)
3143 {
3144         struct mbuf             *m = NULL;
3145         struct rfcomm_mcc_hdr   *hdr = NULL;
3146         struct rfcomm_mcc_pn    *pn = NULL;
3147
3148         mtx_assert(&pcb->session->session_mtx, MA_OWNED);
3149         mtx_assert(&pcb->pcb_mtx, MA_OWNED);
3150
3151         MGETHDR(m, MB_DONTWAIT, MT_DATA);
3152         if (m == NULL)
3153                 return (ENOBUFS);
3154
3155         m->m_pkthdr.len = m->m_len = sizeof(*hdr) + sizeof(*pn);
3156
3157         hdr = mtod(m, struct rfcomm_mcc_hdr *);
3158         pn = (struct rfcomm_mcc_pn *)(hdr + 1);
3159
3160         hdr->type = RFCOMM_MKMCC_TYPE(1, RFCOMM_MCC_PN);
3161         hdr->length = RFCOMM_MKLEN8(sizeof(*pn));
3162
3163         pn->dlci = pcb->dlci;
3164
3165         /*
3166          * Set default DLCI priority as described in GSM 07.10
3167          * (ETSI TS 101 369) clause 5.6 page 42
3168          */
3169
3170         pn->priority = (pcb->dlci < 56)? (((pcb->dlci >> 3) << 3) + 7) : 61;
3171         pn->ack_timer = 0;
3172         pn->mtu = htole16(pcb->mtu);
3173         pn->max_retrans = 0;
3174
3175         if (pcb->flags & NG_BTSOCKET_RFCOMM_DLC_CFC) {
3176                 pn->flow_control = 0xf0;
3177                 pn->credits = pcb->rx_cred;
3178         } else {
3179                 pn->flow_control = 0;
3180                 pn->credits = 0;
3181         }
3182
3183         NG_BTSOCKET_RFCOMM_INFO(
3184 "%s: Sending PN dlci=%d, state=%d, flags=%#x, mtu=%d, flow_control=%#x, " \
3185 "credits=%d\n", __func__, pcb->dlci, pcb->state, pcb->flags, pcb->mtu,
3186                 pn->flow_control, pn->credits);
3187
3188         return (ng_btsocket_rfcomm_send_uih(pcb->session,
3189                         RFCOMM_MKADDRESS(INITIATOR(pcb->session), 0), 0, 0, m));
3190 } /* ng_btsocket_rfcomm_send_pn */
3191
3192 /*
3193  * Calculate and send credits based on available space in receive buffer
3194  */
3195
3196 static int
3197 ng_btsocket_rfcomm_send_credits(ng_btsocket_rfcomm_pcb_p pcb)
3198 {
3199         int             error = 0;
3200         u_int8_t        credits;
3201
3202         mtx_assert(&pcb->pcb_mtx, MA_OWNED);
3203         mtx_assert(&pcb->session->session_mtx, MA_OWNED);
3204
3205         NG_BTSOCKET_RFCOMM_INFO(
3206 "%s: Sending more credits, dlci=%d, state=%d, flags=%#x, mtu=%d, " \
3207 "space=%ld, tx_cred=%d, rx_cred=%d\n",
3208                 __func__, pcb->dlci, pcb->state, pcb->flags, pcb->mtu,
3209                 sbspace(&pcb->so->so_rcv), pcb->tx_cred, pcb->rx_cred);
3210
3211         credits = sbspace(&pcb->so->so_rcv) / pcb->mtu;
3212         if (credits > 0) {
3213                 if (pcb->rx_cred + credits > RFCOMM_MAX_CREDITS)
3214                         credits = RFCOMM_MAX_CREDITS - pcb->rx_cred;
3215
3216                 error = ng_btsocket_rfcomm_send_uih(
3217                                 pcb->session,
3218                                 RFCOMM_MKADDRESS(INITIATOR(pcb->session),
3219                                         pcb->dlci), 1, credits, NULL);
3220                 if (error == 0) {
3221                         pcb->rx_cred += credits;
3222
3223                         NG_BTSOCKET_RFCOMM_INFO(
3224 "%s: Gave remote side %d more credits, dlci=%d, state=%d, flags=%#x, " \
3225 "rx_cred=%d, tx_cred=%d\n",     __func__, credits, pcb->dlci, pcb->state,
3226                                 pcb->flags, pcb->rx_cred, pcb->tx_cred);
3227                 } else
3228                         NG_BTSOCKET_RFCOMM_ERR(
3229 "%s: Could not send credits, error=%d, dlci=%d, state=%d, flags=%#x, " \
3230 "mtu=%d, space=%ld, tx_cred=%d, rx_cred=%d\n",
3231                                 __func__, error, pcb->dlci, pcb->state,
3232                                 pcb->flags, pcb->mtu, sbspace(&pcb->so->so_rcv),
3233                                 pcb->tx_cred, pcb->rx_cred);
3234         }
3235
3236         return (error);
3237 } /* ng_btsocket_rfcomm_send_credits */
3238
3239 /*****************************************************************************
3240  *****************************************************************************
3241  **                              RFCOMM DLCs
3242  *****************************************************************************
3243  *****************************************************************************/
3244
3245 /*
3246  * Send data from socket send buffer
3247  * Caller must hold pcb->pcb_mtx and pcb->session->session_mtx
3248  */
3249
3250 static int
3251 ng_btsocket_rfcomm_pcb_send(ng_btsocket_rfcomm_pcb_p pcb, int limit)
3252 {
3253         struct mbuf     *m = NULL;
3254         int              sent, length, error;
3255
3256         mtx_assert(&pcb->session->session_mtx, MA_OWNED);
3257         mtx_assert(&pcb->pcb_mtx, MA_OWNED);
3258
3259         if (pcb->flags & NG_BTSOCKET_RFCOMM_DLC_CFC)
3260                 limit = min(limit, pcb->tx_cred);
3261         else if (!(pcb->rmodem & RFCOMM_MODEM_FC))
3262                 limit = min(limit, RFCOMM_MAX_CREDITS); /* XXX ??? */
3263         else
3264                 limit = 0;
3265
3266         if (limit == 0) {
3267                 NG_BTSOCKET_RFCOMM_INFO(
3268 "%s: Could not send - remote flow control asserted, dlci=%d, flags=%#x, " \
3269 "rmodem=%#x, tx_cred=%d\n",
3270                         __func__, pcb->dlci, pcb->flags, pcb->rmodem,
3271                         pcb->tx_cred);
3272
3273                 return (0);
3274         }
3275
3276         for (error = 0, sent = 0; sent < limit; sent ++) { 
3277                 length = min(pcb->mtu, pcb->so->so_snd.sb_cc);
3278                 if (length == 0)
3279                         break;
3280
3281                 /* Get the chunk from the socket's send buffer */
3282                 m = ng_btsocket_rfcomm_prepare_packet(&pcb->so->so_snd, length);
3283                 if (m == NULL) {
3284                         error = ENOBUFS;
3285                         break;
3286                 }
3287
3288                 sbdrop(&pcb->so->so_snd, length);
3289
3290                 error = ng_btsocket_rfcomm_send_uih(pcb->session,
3291                                 RFCOMM_MKADDRESS(INITIATOR(pcb->session),
3292                                         pcb->dlci), 0, 0, m);
3293                 if (error != 0)
3294                         break;
3295         }
3296
3297         if (pcb->flags & NG_BTSOCKET_RFCOMM_DLC_CFC)
3298                 pcb->tx_cred -= sent;
3299
3300         if (error == 0 && sent > 0) {
3301                 pcb->flags &= ~NG_BTSOCKET_RFCOMM_DLC_SENDING;
3302                 sowwakeup(pcb->so);
3303         }
3304
3305         return (error);
3306 } /* ng_btsocket_rfcomm_pcb_send */
3307
3308 /*
3309  * Unlink and disconnect DLC. If ng_btsocket_rfcomm_pcb_kill() returns
3310  * non zero value than socket has no reference and has to be detached.
3311  * Caller must hold pcb->pcb_mtx and pcb->session->session_mtx
3312  */
3313
3314 static void
3315 ng_btsocket_rfcomm_pcb_kill(ng_btsocket_rfcomm_pcb_p pcb, int error)
3316 {
3317         ng_btsocket_rfcomm_session_p    s = pcb->session;
3318
3319         NG_BTSOCKET_RFCOMM_INFO(
3320 "%s: Killing DLC, so=%p, dlci=%d, state=%d, flags=%#x, error=%d\n",
3321                 __func__, pcb->so, pcb->dlci, pcb->state, pcb->flags, error);
3322
3323         if (pcb->session == NULL)
3324                 panic("%s: DLC without session, pcb=%p, state=%d, flags=%#x\n",
3325                         __func__, pcb, pcb->state, pcb->flags);
3326
3327         mtx_assert(&pcb->session->session_mtx, MA_OWNED);
3328         mtx_assert(&pcb->pcb_mtx, MA_OWNED);
3329
3330         if (pcb->flags & NG_BTSOCKET_RFCOMM_DLC_TIMO)
3331                 ng_btsocket_rfcomm_untimeout(pcb);
3332
3333         /* Detach DLC from the session. Does not matter which state DLC in */
3334         LIST_REMOVE(pcb, session_next);
3335         pcb->session = NULL;
3336
3337         /* Change DLC state and wakeup all sleepers */
3338         pcb->state = NG_BTSOCKET_RFCOMM_DLC_CLOSED;
3339         pcb->so->so_error = error;
3340         soisdisconnected(pcb->so);
3341         wakeup(&pcb->state);
3342
3343         /* Check if we have any DLCs left on the session */
3344         if (LIST_EMPTY(&s->dlcs) && INITIATOR(s)) {
3345                 NG_BTSOCKET_RFCOMM_INFO(
3346 "%s: Disconnecting session, state=%d, flags=%#x, mtu=%d\n",
3347                         __func__, s->state, s->flags, s->mtu);
3348
3349                 switch (s->state) {
3350                 case NG_BTSOCKET_RFCOMM_SESSION_CLOSED:
3351                 case NG_BTSOCKET_RFCOMM_SESSION_DISCONNECTING:
3352                         /*
3353                          * Do not have to do anything here. We can get here
3354                          * when L2CAP connection was terminated or we have 
3355                          * received DISC on multiplexor channel
3356                          */
3357                         break;
3358
3359                 case NG_BTSOCKET_RFCOMM_SESSION_OPEN:
3360                         /* Send DISC on multiplexor channel */
3361                         error = ng_btsocket_rfcomm_send_command(s,
3362                                         RFCOMM_FRAME_DISC, 0);
3363                         if (error == 0) {
3364                                 s->state = NG_BTSOCKET_RFCOMM_SESSION_DISCONNECTING;
3365                                 break;
3366                         }
3367                         /* FALL THROUGH */
3368
3369                 case NG_BTSOCKET_RFCOMM_SESSION_CONNECTING:
3370                 case NG_BTSOCKET_RFCOMM_SESSION_CONNECTED:
3371                         s->state = NG_BTSOCKET_RFCOMM_SESSION_CLOSED;
3372                         break;
3373
3374 /*              case NG_BTSOCKET_RFCOMM_SESSION_LISTENING: */
3375                 default:
3376                         panic("%s: Invalid session state=%d, flags=%#x\n",
3377                                 __func__, s->state, s->flags);
3378                         break;
3379                 }
3380
3381                 ng_btsocket_rfcomm_task_wakeup();
3382         }
3383 } /* ng_btsocket_rfcomm_pcb_kill */
3384
3385 /*
3386  * Look for given dlci for given RFCOMM session. Caller must hold s->session_mtx
3387  */
3388
3389 static ng_btsocket_rfcomm_pcb_p
3390 ng_btsocket_rfcomm_pcb_by_dlci(ng_btsocket_rfcomm_session_p s, int dlci)
3391 {
3392         ng_btsocket_rfcomm_pcb_p        pcb = NULL;
3393
3394         mtx_assert(&s->session_mtx, MA_OWNED);
3395
3396         LIST_FOREACH(pcb, &s->dlcs, session_next)
3397                 if (pcb->dlci == dlci)
3398                         break;
3399
3400         return (pcb);
3401 } /* ng_btsocket_rfcomm_pcb_by_dlci */
3402
3403 /*
3404  * Look for socket that listens on given src address and given channel
3405  */
3406
3407 static ng_btsocket_rfcomm_pcb_p
3408 ng_btsocket_rfcomm_pcb_listener(bdaddr_p src, int channel)
3409 {
3410         ng_btsocket_rfcomm_pcb_p        pcb = NULL, pcb1 = NULL;
3411
3412         mtx_lock(&ng_btsocket_rfcomm_sockets_mtx);
3413
3414         LIST_FOREACH(pcb, &ng_btsocket_rfcomm_sockets, next) {
3415                 if (pcb->channel != channel ||
3416                     !(pcb->so->so_options & SO_ACCEPTCONN))
3417                         continue;
3418
3419                 if (bcmp(&pcb->src, src, sizeof(*src)) == 0)
3420                         break;
3421
3422                 if (bcmp(&pcb->src, NG_HCI_BDADDR_ANY, sizeof(bdaddr_t)) == 0)
3423                         pcb1 = pcb;
3424         }
3425
3426         mtx_unlock(&ng_btsocket_rfcomm_sockets_mtx);
3427
3428         return ((pcb != NULL)? pcb : pcb1);
3429 } /* ng_btsocket_rfcomm_pcb_listener */
3430
3431 /*****************************************************************************
3432  *****************************************************************************
3433  **                              Misc. functions 
3434  *****************************************************************************
3435  *****************************************************************************/
3436
3437 /*
3438  *  Set timeout. Caller MUST hold pcb_mtx
3439  */
3440
3441 static void
3442 ng_btsocket_rfcomm_timeout(ng_btsocket_rfcomm_pcb_p pcb)
3443 {
3444         mtx_assert(&pcb->pcb_mtx, MA_OWNED);
3445
3446         if (!(pcb->flags & NG_BTSOCKET_RFCOMM_DLC_TIMO)) {
3447                 pcb->flags |= NG_BTSOCKET_RFCOMM_DLC_TIMO;
3448                 pcb->flags &= ~NG_BTSOCKET_RFCOMM_DLC_TIMEDOUT;
3449                 pcb->timo = timeout(ng_btsocket_rfcomm_process_timeout, pcb,
3450                                         ng_btsocket_rfcomm_timo * hz);
3451         } else
3452                 panic("%s: Duplicated socket timeout?!\n", __func__);
3453 } /* ng_btsocket_rfcomm_timeout */
3454
3455 /*
3456  *  Unset pcb timeout. Caller MUST hold pcb_mtx
3457  */
3458
3459 static void
3460 ng_btsocket_rfcomm_untimeout(ng_btsocket_rfcomm_pcb_p pcb)
3461 {
3462         mtx_assert(&pcb->pcb_mtx, MA_OWNED);
3463
3464         if (pcb->flags & NG_BTSOCKET_RFCOMM_DLC_TIMO) {
3465                 untimeout(ng_btsocket_rfcomm_process_timeout, pcb, pcb->timo);
3466                 pcb->flags &= ~NG_BTSOCKET_RFCOMM_DLC_TIMO;
3467                 pcb->flags &= ~NG_BTSOCKET_RFCOMM_DLC_TIMEDOUT;
3468         } else
3469                 panic("%s: No socket timeout?!\n", __func__);
3470 } /* ng_btsocket_rfcomm_timeout */
3471
3472 /*
3473  * Process pcb timeout
3474  */
3475
3476 static void
3477 ng_btsocket_rfcomm_process_timeout(void *xpcb)
3478 {
3479         ng_btsocket_rfcomm_pcb_p        pcb = (ng_btsocket_rfcomm_pcb_p) xpcb;
3480
3481         mtx_lock(&pcb->pcb_mtx);
3482
3483         NG_BTSOCKET_RFCOMM_INFO(
3484 "%s: Timeout, so=%p, dlci=%d, state=%d, flags=%#x\n",
3485                 __func__, pcb->so, pcb->dlci, pcb->state, pcb->flags);
3486
3487         pcb->flags &= ~NG_BTSOCKET_RFCOMM_DLC_TIMO;
3488         pcb->flags |= NG_BTSOCKET_RFCOMM_DLC_TIMEDOUT;
3489
3490         switch (pcb->state) {
3491         case NG_BTSOCKET_RFCOMM_DLC_CONFIGURING:
3492         case NG_BTSOCKET_RFCOMM_DLC_CONNECTING:
3493                 pcb->state = NG_BTSOCKET_RFCOMM_DLC_DISCONNECTING;
3494                 break;
3495
3496         case NG_BTSOCKET_RFCOMM_DLC_W4_CONNECT:
3497         case NG_BTSOCKET_RFCOMM_DLC_DISCONNECTING:
3498                 break;
3499
3500         default:
3501                 panic(
3502 "%s: DLC timeout in invalid state, dlci=%d, state=%d, flags=%#x\n",
3503                         __func__, pcb->dlci, pcb->state, pcb->flags);
3504                 break;
3505         }
3506
3507         ng_btsocket_rfcomm_task_wakeup();
3508
3509         mtx_unlock(&pcb->pcb_mtx);
3510 } /* ng_btsocket_rfcomm_process_timeout */
3511
3512 /*
3513  * Get up to length bytes from the socket buffer
3514  */
3515
3516 static struct mbuf *
3517 ng_btsocket_rfcomm_prepare_packet(struct sockbuf *sb, int length)
3518 {
3519         struct mbuf     *top = NULL, *m = NULL, *n = NULL, *nextpkt = NULL;
3520         int              mlen, noff, len;
3521
3522         MGETHDR(top, MB_DONTWAIT, MT_DATA);
3523         if (top == NULL)
3524                 return (NULL);
3525
3526         top->m_pkthdr.len = length;
3527         top->m_len = 0;
3528         mlen = MHLEN;
3529
3530         m = top;
3531         n = sb->sb_mb;
3532         nextpkt = n->m_nextpkt;
3533         noff = 0;
3534
3535         while (length > 0 && n != NULL) {
3536                 len = min(mlen - m->m_len, n->m_len - noff);
3537                 if (len > length)
3538                         len = length;
3539
3540                 bcopy(mtod(n, caddr_t)+noff, mtod(m, caddr_t)+m->m_len, len);
3541                 m->m_len += len;
3542                 noff += len;
3543                 length -= len;
3544
3545                 if (length > 0 && m->m_len == mlen) {
3546                         MGET(m->m_next, MB_DONTWAIT, MT_DATA);
3547                         if (m->m_next == NULL) {
3548                                 NG_FREE_M(top);
3549                                 return (NULL);
3550                         }
3551
3552                         m = m->m_next;
3553                         m->m_len = 0;
3554                         mlen = MLEN;
3555                 }
3556
3557                 if (noff == n->m_len) {
3558                         noff = 0;
3559                         n = n->m_next;
3560
3561                         if (n == NULL)
3562                                 n = nextpkt;
3563
3564                         nextpkt = (n != NULL)? n->m_nextpkt : NULL;
3565                 }
3566         }
3567
3568         if (length < 0)
3569                 panic("%s: length=%d\n", __func__, length);
3570         if (length > 0 && n == NULL)
3571                 panic("%s: bogus length=%d, n=%p\n", __func__, length, n);
3572
3573         return (top);
3574 } /* ng_btsocket_rfcomm_prepare_packet */
3575