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