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