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