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