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