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