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