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