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