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