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