6 * Copyright (c) 2001-2003 Maksim Yevmenkin <m_evmenkin@yahoo.com>
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
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.
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
30 * $Id: ng_btsocket_rfcomm.c,v 1.28 2003/09/14 23:29:06 max Exp $
31 * $FreeBSD: src/sys/netgraph/bluetooth/socket/ng_btsocket_rfcomm.c,v 1.27 2007/10/29 19:06:47 emax Exp $
32 * $DragonFly: src/sys/netgraph7/bluetooth/socket/ng_btsocket_rfcomm.c,v 1.2 2008/06/26 23:05:40 dillon Exp $
35 #include <sys/param.h>
36 #include <sys/systm.h>
37 #include <sys/bitstring.h>
38 #include <sys/domain.h>
39 #include <sys/endian.h>
40 #include <sys/errno.h>
41 #include <sys/filedesc.h>
42 #include <sys/kernel.h>
44 #include <sys/malloc.h>
46 #include <sys/mutex.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>
55 #include "ng_message.h"
57 #include "bluetooth/include/ng_bluetooth.h"
58 #include "bluetooth/include/ng_hci.h"
59 #include "bluetooth/include/ng_l2cap.h"
60 #include "bluetooth/include/ng_btsocket.h"
61 #include "bluetooth/include/ng_btsocket_l2cap.h"
62 #include "bluetooth/include/ng_btsocket_rfcomm.h"
65 #ifdef NG_SEPARATE_MALLOC
66 MALLOC_DEFINE(M_NETGRAPH_BTSOCKET_RFCOMM, "netgraph_btsocks_rfcomm",
67 "Netgraph Bluetooth RFCOMM sockets");
69 #define M_NETGRAPH_BTSOCKET_RFCOMM M_NETGRAPH
70 #endif /* NG_SEPARATE_MALLOC */
73 #define NG_BTSOCKET_RFCOMM_INFO \
74 if (ng_btsocket_rfcomm_debug_level >= NG_BTSOCKET_INFO_LEVEL) \
77 #define NG_BTSOCKET_RFCOMM_WARN \
78 if (ng_btsocket_rfcomm_debug_level >= NG_BTSOCKET_WARN_LEVEL) \
81 #define NG_BTSOCKET_RFCOMM_ERR \
82 if (ng_btsocket_rfcomm_debug_level >= NG_BTSOCKET_ERR_LEVEL) \
85 #define NG_BTSOCKET_RFCOMM_ALERT \
86 if (ng_btsocket_rfcomm_debug_level >= NG_BTSOCKET_ALERT_LEVEL) \
91 /* Local prototypes */
92 static void ng_btsocket_rfcomm_upcall
93 (struct socket *so, void *arg, int waitflag);
94 static void ng_btsocket_rfcomm_sessions_task
95 (void *ctx, int pending);
96 static void ng_btsocket_rfcomm_session_task
97 (ng_btsocket_rfcomm_session_p s);
98 #define ng_btsocket_rfcomm_task_wakeup() \
99 taskqueue_enqueue(taskqueue_swi_giant, &ng_btsocket_rfcomm_task)
101 static ng_btsocket_rfcomm_pcb_p ng_btsocket_rfcomm_connect_ind
102 (ng_btsocket_rfcomm_session_p s, int channel);
103 static void ng_btsocket_rfcomm_connect_cfm
104 (ng_btsocket_rfcomm_session_p s);
106 static int ng_btsocket_rfcomm_session_create
107 (ng_btsocket_rfcomm_session_p *sp, struct socket *l2so,
108 bdaddr_p src, bdaddr_p dst, struct thread *td);
109 static int ng_btsocket_rfcomm_session_accept
110 (ng_btsocket_rfcomm_session_p s0);
111 static int ng_btsocket_rfcomm_session_connect
112 (ng_btsocket_rfcomm_session_p s);
113 static int ng_btsocket_rfcomm_session_receive
114 (ng_btsocket_rfcomm_session_p s);
115 static int ng_btsocket_rfcomm_session_send
116 (ng_btsocket_rfcomm_session_p s);
117 static void ng_btsocket_rfcomm_session_clean
118 (ng_btsocket_rfcomm_session_p s);
119 static void ng_btsocket_rfcomm_session_process_pcb
120 (ng_btsocket_rfcomm_session_p s);
121 static ng_btsocket_rfcomm_session_p ng_btsocket_rfcomm_session_by_addr
122 (bdaddr_p src, bdaddr_p dst);
124 static int ng_btsocket_rfcomm_receive_frame
125 (ng_btsocket_rfcomm_session_p s, struct mbuf *m0);
126 static int ng_btsocket_rfcomm_receive_sabm
127 (ng_btsocket_rfcomm_session_p s, int dlci);
128 static int ng_btsocket_rfcomm_receive_disc
129 (ng_btsocket_rfcomm_session_p s, int dlci);
130 static int ng_btsocket_rfcomm_receive_ua
131 (ng_btsocket_rfcomm_session_p s, int dlci);
132 static int ng_btsocket_rfcomm_receive_dm
133 (ng_btsocket_rfcomm_session_p s, int dlci);
134 static int ng_btsocket_rfcomm_receive_uih
135 (ng_btsocket_rfcomm_session_p s, int dlci, int pf, struct mbuf *m0);
136 static int ng_btsocket_rfcomm_receive_mcc
137 (ng_btsocket_rfcomm_session_p s, struct mbuf *m0);
138 static int ng_btsocket_rfcomm_receive_test
139 (ng_btsocket_rfcomm_session_p s, struct mbuf *m0);
140 static int ng_btsocket_rfcomm_receive_fc
141 (ng_btsocket_rfcomm_session_p s, struct mbuf *m0);
142 static int ng_btsocket_rfcomm_receive_msc
143 (ng_btsocket_rfcomm_session_p s, struct mbuf *m0);
144 static int ng_btsocket_rfcomm_receive_rpn
145 (ng_btsocket_rfcomm_session_p s, struct mbuf *m0);
146 static int ng_btsocket_rfcomm_receive_rls
147 (ng_btsocket_rfcomm_session_p s, struct mbuf *m0);
148 static int ng_btsocket_rfcomm_receive_pn
149 (ng_btsocket_rfcomm_session_p s, struct mbuf *m0);
150 static void ng_btsocket_rfcomm_set_pn
151 (ng_btsocket_rfcomm_pcb_p pcb, u_int8_t cr, u_int8_t flow_control,
152 u_int8_t credits, u_int16_t mtu);
154 static int ng_btsocket_rfcomm_send_command
155 (ng_btsocket_rfcomm_session_p s, u_int8_t type, u_int8_t dlci);
156 static int ng_btsocket_rfcomm_send_uih
157 (ng_btsocket_rfcomm_session_p s, u_int8_t address, u_int8_t pf,
158 u_int8_t credits, struct mbuf *data);
159 static int ng_btsocket_rfcomm_send_msc
160 (ng_btsocket_rfcomm_pcb_p pcb);
161 static int ng_btsocket_rfcomm_send_pn
162 (ng_btsocket_rfcomm_pcb_p pcb);
163 static int ng_btsocket_rfcomm_send_credits
164 (ng_btsocket_rfcomm_pcb_p pcb);
166 static int ng_btsocket_rfcomm_pcb_send
167 (ng_btsocket_rfcomm_pcb_p pcb, int limit);
168 static void ng_btsocket_rfcomm_pcb_kill
169 (ng_btsocket_rfcomm_pcb_p pcb, int error);
170 static ng_btsocket_rfcomm_pcb_p ng_btsocket_rfcomm_pcb_by_dlci
171 (ng_btsocket_rfcomm_session_p s, int dlci);
172 static ng_btsocket_rfcomm_pcb_p ng_btsocket_rfcomm_pcb_listener
173 (bdaddr_p src, int channel);
175 static void ng_btsocket_rfcomm_timeout
176 (ng_btsocket_rfcomm_pcb_p pcb);
177 static void ng_btsocket_rfcomm_untimeout
178 (ng_btsocket_rfcomm_pcb_p pcb);
179 static void ng_btsocket_rfcomm_process_timeout
182 static struct mbuf * ng_btsocket_rfcomm_prepare_packet
183 (struct sockbuf *sb, int length);
186 extern int ifqmaxlen;
187 static u_int32_t ng_btsocket_rfcomm_debug_level;
188 static u_int32_t ng_btsocket_rfcomm_timo;
189 struct task ng_btsocket_rfcomm_task;
190 static LIST_HEAD(, ng_btsocket_rfcomm_session) ng_btsocket_rfcomm_sessions;
191 static struct mtx ng_btsocket_rfcomm_sessions_mtx;
192 static LIST_HEAD(, ng_btsocket_rfcomm_pcb) ng_btsocket_rfcomm_sockets;
193 static struct mtx ng_btsocket_rfcomm_sockets_mtx;
196 SYSCTL_DECL(_net_bluetooth_rfcomm_sockets);
197 SYSCTL_NODE(_net_bluetooth_rfcomm_sockets, OID_AUTO, stream, CTLFLAG_RW,
198 0, "Bluetooth STREAM RFCOMM sockets family");
199 SYSCTL_INT(_net_bluetooth_rfcomm_sockets_stream, OID_AUTO, debug_level,
201 &ng_btsocket_rfcomm_debug_level, NG_BTSOCKET_INFO_LEVEL,
202 "Bluetooth STREAM RFCOMM sockets debug level");
203 SYSCTL_INT(_net_bluetooth_rfcomm_sockets_stream, OID_AUTO, timeout,
205 &ng_btsocket_rfcomm_timo, 60,
206 "Bluetooth STREAM RFCOMM sockets timeout");
208 /*****************************************************************************
209 *****************************************************************************
211 *****************************************************************************
212 *****************************************************************************/
214 static u_int8_t ng_btsocket_rfcomm_crc_table[256] = {
215 0x00, 0x91, 0xe3, 0x72, 0x07, 0x96, 0xe4, 0x75,
216 0x0e, 0x9f, 0xed, 0x7c, 0x09, 0x98, 0xea, 0x7b,
217 0x1c, 0x8d, 0xff, 0x6e, 0x1b, 0x8a, 0xf8, 0x69,
218 0x12, 0x83, 0xf1, 0x60, 0x15, 0x84, 0xf6, 0x67,
220 0x38, 0xa9, 0xdb, 0x4a, 0x3f, 0xae, 0xdc, 0x4d,
221 0x36, 0xa7, 0xd5, 0x44, 0x31, 0xa0, 0xd2, 0x43,
222 0x24, 0xb5, 0xc7, 0x56, 0x23, 0xb2, 0xc0, 0x51,
223 0x2a, 0xbb, 0xc9, 0x58, 0x2d, 0xbc, 0xce, 0x5f,
225 0x70, 0xe1, 0x93, 0x02, 0x77, 0xe6, 0x94, 0x05,
226 0x7e, 0xef, 0x9d, 0x0c, 0x79, 0xe8, 0x9a, 0x0b,
227 0x6c, 0xfd, 0x8f, 0x1e, 0x6b, 0xfa, 0x88, 0x19,
228 0x62, 0xf3, 0x81, 0x10, 0x65, 0xf4, 0x86, 0x17,
230 0x48, 0xd9, 0xab, 0x3a, 0x4f, 0xde, 0xac, 0x3d,
231 0x46, 0xd7, 0xa5, 0x34, 0x41, 0xd0, 0xa2, 0x33,
232 0x54, 0xc5, 0xb7, 0x26, 0x53, 0xc2, 0xb0, 0x21,
233 0x5a, 0xcb, 0xb9, 0x28, 0x5d, 0xcc, 0xbe, 0x2f,
235 0xe0, 0x71, 0x03, 0x92, 0xe7, 0x76, 0x04, 0x95,
236 0xee, 0x7f, 0x0d, 0x9c, 0xe9, 0x78, 0x0a, 0x9b,
237 0xfc, 0x6d, 0x1f, 0x8e, 0xfb, 0x6a, 0x18, 0x89,
238 0xf2, 0x63, 0x11, 0x80, 0xf5, 0x64, 0x16, 0x87,
240 0xd8, 0x49, 0x3b, 0xaa, 0xdf, 0x4e, 0x3c, 0xad,
241 0xd6, 0x47, 0x35, 0xa4, 0xd1, 0x40, 0x32, 0xa3,
242 0xc4, 0x55, 0x27, 0xb6, 0xc3, 0x52, 0x20, 0xb1,
243 0xca, 0x5b, 0x29, 0xb8, 0xcd, 0x5c, 0x2e, 0xbf,
245 0x90, 0x01, 0x73, 0xe2, 0x97, 0x06, 0x74, 0xe5,
246 0x9e, 0x0f, 0x7d, 0xec, 0x99, 0x08, 0x7a, 0xeb,
247 0x8c, 0x1d, 0x6f, 0xfe, 0x8b, 0x1a, 0x68, 0xf9,
248 0x82, 0x13, 0x61, 0xf0, 0x85, 0x14, 0x66, 0xf7,
250 0xa8, 0x39, 0x4b, 0xda, 0xaf, 0x3e, 0x4c, 0xdd,
251 0xa6, 0x37, 0x45, 0xd4, 0xa1, 0x30, 0x42, 0xd3,
252 0xb4, 0x25, 0x57, 0xc6, 0xb3, 0x22, 0x50, 0xc1,
253 0xba, 0x2b, 0x59, 0xc8, 0xbd, 0x2c, 0x5e, 0xcf
258 ng_btsocket_rfcomm_crc(u_int8_t *data, int length)
263 crc = ng_btsocket_rfcomm_crc_table[crc ^ *data++];
266 } /* ng_btsocket_rfcomm_crc */
270 ng_btsocket_rfcomm_fcs2(u_int8_t *data)
272 return (0xff - ng_btsocket_rfcomm_crc(data, 2));
273 } /* ng_btsocket_rfcomm_fcs2 */
277 ng_btsocket_rfcomm_fcs3(u_int8_t *data)
279 return (0xff - ng_btsocket_rfcomm_crc(data, 3));
280 } /* ng_btsocket_rfcomm_fcs3 */
285 * From Bluetooth spec
287 * "... In 07.10, the frame check sequence (FCS) is calculated on different
288 * sets of fields for different frame types. These are the fields that the
289 * FCS are calculated on:
291 * For SABM, DISC, UA, DM frames: on Address, Control and length field.
292 * For UIH frames: on Address and Control field.
294 * (This is stated here for clarification, and to set the standard for RFCOMM;
295 * the fields included in FCS calculation have actually changed in version
296 * 7.0.0 of TS 07.10, but RFCOMM will not change the FCS calculation scheme
297 * from the one above.) ..."
301 ng_btsocket_rfcomm_check_fcs(u_int8_t *data, int type, u_int8_t fcs)
303 if (type != RFCOMM_FRAME_UIH)
304 return (ng_btsocket_rfcomm_fcs3(data) != fcs);
306 return (ng_btsocket_rfcomm_fcs2(data) != fcs);
307 } /* ng_btsocket_rfcomm_check_fcs */
309 /*****************************************************************************
310 *****************************************************************************
312 *****************************************************************************
313 *****************************************************************************/
316 * Initialize everything
320 ng_btsocket_rfcomm_init(void)
322 ng_btsocket_rfcomm_debug_level = NG_BTSOCKET_WARN_LEVEL;
323 ng_btsocket_rfcomm_timo = 60;
326 TASK_INIT(&ng_btsocket_rfcomm_task, 0,
327 ng_btsocket_rfcomm_sessions_task, NULL);
329 /* RFCOMM sessions list */
330 LIST_INIT(&ng_btsocket_rfcomm_sessions);
331 mtx_init(&ng_btsocket_rfcomm_sessions_mtx,
332 "btsocks_rfcomm_sessions_mtx", NULL, MTX_DEF);
334 /* RFCOMM sockets list */
335 LIST_INIT(&ng_btsocket_rfcomm_sockets);
336 mtx_init(&ng_btsocket_rfcomm_sockets_mtx,
337 "btsocks_rfcomm_sockets_mtx", NULL, MTX_DEF);
338 } /* ng_btsocket_rfcomm_init */
341 * Abort connection on socket
345 ng_btsocket_rfcomm_abort(struct socket *so)
348 so->so_error = ECONNABORTED;
349 (void)ng_btsocket_rfcomm_disconnect(so);
350 } /* ng_btsocket_rfcomm_abort */
353 ng_btsocket_rfcomm_close(struct socket *so)
356 (void)ng_btsocket_rfcomm_disconnect(so);
357 } /* ng_btsocket_rfcomm_close */
360 * Accept connection on socket. Nothing to do here, socket must be connected
361 * and ready, so just return peer address and be done with it.
365 ng_btsocket_rfcomm_accept(struct socket *so, struct sockaddr **nam)
367 return (ng_btsocket_rfcomm_peeraddr(so, nam));
368 } /* ng_btsocket_rfcomm_accept */
371 * Create and attach new socket
375 ng_btsocket_rfcomm_attach(struct socket *so, int proto, struct thread *td)
377 ng_btsocket_rfcomm_pcb_p pcb = so2rfcomm_pcb(so);
380 /* Check socket and protocol */
381 if (so->so_type != SOCK_STREAM)
382 return (ESOCKTNOSUPPORT);
384 #if 0 /* XXX sonewconn() calls "pru_attach" with proto == 0 */
386 if (proto != BLUETOOTH_PROTO_RFCOMM)
387 return (EPROTONOSUPPORT);
393 /* Reserve send and receive space if it is not reserved yet */
394 if ((so->so_snd.sb_hiwat == 0) || (so->so_rcv.sb_hiwat == 0)) {
395 error = soreserve(so, NG_BTSOCKET_RFCOMM_SENDSPACE,
396 NG_BTSOCKET_RFCOMM_RECVSPACE);
401 /* Allocate the PCB */
402 MALLOC(pcb, ng_btsocket_rfcomm_pcb_p, sizeof(*pcb),
403 M_NETGRAPH_BTSOCKET_RFCOMM, M_WAITOK | M_NULLOK | M_ZERO);
407 /* Link the PCB and the socket */
408 so->so_pcb = (caddr_t) pcb;
412 pcb->state = NG_BTSOCKET_RFCOMM_DLC_CLOSED;
413 pcb->flags = NG_BTSOCKET_RFCOMM_DLC_CFC;
416 pcb->rmodem = (RFCOMM_MODEM_RTC | RFCOMM_MODEM_RTR | RFCOMM_MODEM_DV);
418 pcb->mtu = RFCOMM_DEFAULT_MTU;
420 pcb->rx_cred = RFCOMM_DEFAULT_CREDITS;
422 mtx_init(&pcb->pcb_mtx, "btsocks_rfcomm_pcb_mtx", NULL, MTX_DEF);
423 callout_handle_init(&pcb->timo);
425 /* Add the PCB to the list */
426 mtx_lock(&ng_btsocket_rfcomm_sockets_mtx);
427 LIST_INSERT_HEAD(&ng_btsocket_rfcomm_sockets, pcb, next);
428 mtx_unlock(&ng_btsocket_rfcomm_sockets_mtx);
431 } /* ng_btsocket_rfcomm_attach */
438 ng_btsocket_rfcomm_bind(struct socket *so, struct sockaddr *nam,
441 ng_btsocket_rfcomm_pcb_t *pcb = so2rfcomm_pcb(so), *pcb1;
442 struct sockaddr_rfcomm *sa = (struct sockaddr_rfcomm *) nam;
450 if (sa->rfcomm_family != AF_BLUETOOTH)
451 return (EAFNOSUPPORT);
452 if (sa->rfcomm_len != sizeof(*sa))
454 if (sa->rfcomm_channel > 30)
457 mtx_lock(&pcb->pcb_mtx);
459 if (sa->rfcomm_channel != 0) {
460 mtx_lock(&ng_btsocket_rfcomm_sockets_mtx);
462 LIST_FOREACH(pcb1, &ng_btsocket_rfcomm_sockets, next) {
463 if (pcb1->channel == sa->rfcomm_channel &&
464 bcmp(&pcb1->src, &sa->rfcomm_bdaddr,
465 sizeof(pcb1->src)) == 0) {
466 mtx_unlock(&ng_btsocket_rfcomm_sockets_mtx);
467 mtx_unlock(&pcb->pcb_mtx);
473 mtx_unlock(&ng_btsocket_rfcomm_sockets_mtx);
476 bcopy(&sa->rfcomm_bdaddr, &pcb->src, sizeof(pcb->src));
477 pcb->channel = sa->rfcomm_channel;
479 mtx_unlock(&pcb->pcb_mtx);
482 } /* ng_btsocket_rfcomm_bind */
489 ng_btsocket_rfcomm_connect(struct socket *so, struct sockaddr *nam,
492 ng_btsocket_rfcomm_pcb_t *pcb = so2rfcomm_pcb(so);
493 struct sockaddr_rfcomm *sa = (struct sockaddr_rfcomm *) nam;
494 ng_btsocket_rfcomm_session_t *s = NULL;
495 struct socket *l2so = NULL;
504 if (sa->rfcomm_family != AF_BLUETOOTH)
505 return (EAFNOSUPPORT);
506 if (sa->rfcomm_len != sizeof(*sa))
508 if (sa->rfcomm_channel > 30)
510 if (sa->rfcomm_channel == 0 ||
511 bcmp(&sa->rfcomm_bdaddr, NG_HCI_BDADDR_ANY, sizeof(bdaddr_t)) == 0)
512 return (EDESTADDRREQ);
515 * XXX FIXME - This is FUBAR. socreate() will call soalloc(1), i.e.
516 * soalloc() is allowed to sleep in MALLOC. This creates "could sleep"
517 * WITNESS warnings. To work around this problem we will create L2CAP
518 * socket first and then check if we actually need it. Note that we
519 * will not check for errors in socreate() because if we failed to
520 * create L2CAP socket at this point we still might have already open
524 error = socreate(PF_BLUETOOTH, &l2so, SOCK_SEQPACKET,
525 BLUETOOTH_PROTO_L2CAP, td->td_ucred, td);
528 * Look for session between "pcb->src" and "sa->rfcomm_bdaddr" (dst)
531 mtx_lock(&ng_btsocket_rfcomm_sessions_mtx);
533 s = ng_btsocket_rfcomm_session_by_addr(&pcb->src, &sa->rfcomm_bdaddr);
536 * We need to create new RFCOMM session. Check if we have L2CAP
537 * socket. If l2so == NULL then error has the error code from
542 mtx_unlock(&ng_btsocket_rfcomm_sessions_mtx);
546 error = ng_btsocket_rfcomm_session_create(&s, l2so,
547 &pcb->src, &sa->rfcomm_bdaddr, td);
549 mtx_unlock(&ng_btsocket_rfcomm_sessions_mtx);
554 } else if (l2so != NULL)
555 soclose(l2so); /* we don't need new L2CAP socket */
558 * Check if we already have the same DLCI the the same session
561 mtx_lock(&s->session_mtx);
562 mtx_lock(&pcb->pcb_mtx);
564 dlci = RFCOMM_MKDLCI(!INITIATOR(s), sa->rfcomm_channel);
566 if (ng_btsocket_rfcomm_pcb_by_dlci(s, dlci) != NULL) {
567 mtx_unlock(&pcb->pcb_mtx);
568 mtx_unlock(&s->session_mtx);
569 mtx_unlock(&ng_btsocket_rfcomm_sessions_mtx);
575 * Check session state and if its not acceptable then refuse connection
579 case NG_BTSOCKET_RFCOMM_SESSION_CONNECTING:
580 case NG_BTSOCKET_RFCOMM_SESSION_CONNECTED:
581 case NG_BTSOCKET_RFCOMM_SESSION_OPEN:
583 * Update destination address and channel and attach
587 bcopy(&sa->rfcomm_bdaddr, &pcb->dst, sizeof(pcb->dst));
588 pcb->channel = sa->rfcomm_channel;
591 LIST_INSERT_HEAD(&s->dlcs, pcb, session_next);
594 ng_btsocket_rfcomm_timeout(pcb);
595 soisconnecting(pcb->so);
597 if (s->state == NG_BTSOCKET_RFCOMM_SESSION_OPEN) {
599 bcopy(&so2l2cap_pcb(s->l2so)->src, &pcb->src,
602 pcb->state = NG_BTSOCKET_RFCOMM_DLC_CONFIGURING;
604 error = ng_btsocket_rfcomm_send_pn(pcb);
606 error = ng_btsocket_rfcomm_task_wakeup();
608 pcb->state = NG_BTSOCKET_RFCOMM_DLC_W4_CONNECT;
616 mtx_unlock(&pcb->pcb_mtx);
617 mtx_unlock(&s->session_mtx);
618 mtx_unlock(&ng_btsocket_rfcomm_sessions_mtx);
621 } /* ng_btsocket_rfcomm_connect */
624 * Process ioctl's calls on socket.
625 * XXX FIXME this should provide interface to the RFCOMM multiplexor channel
629 ng_btsocket_rfcomm_control(struct socket *so, u_long cmd, caddr_t data,
630 struct ifnet *ifp, struct thread *td)
633 } /* ng_btsocket_rfcomm_control */
636 * Process getsockopt/setsockopt system calls
640 ng_btsocket_rfcomm_ctloutput(struct socket *so, struct sockopt *sopt)
642 ng_btsocket_rfcomm_pcb_p pcb = so2rfcomm_pcb(so);
643 struct ng_btsocket_rfcomm_fc_info fcinfo;
648 if (sopt->sopt_level != SOL_RFCOMM)
651 mtx_lock(&pcb->pcb_mtx);
653 switch (sopt->sopt_dir) {
655 switch (sopt->sopt_name) {
657 error = sooptcopyout(sopt, &pcb->mtu, sizeof(pcb->mtu));
660 case SO_RFCOMM_FC_INFO:
661 fcinfo.lmodem = pcb->lmodem;
662 fcinfo.rmodem = pcb->rmodem;
663 fcinfo.tx_cred = pcb->tx_cred;
664 fcinfo.rx_cred = pcb->rx_cred;
665 fcinfo.cfc = (pcb->flags & NG_BTSOCKET_RFCOMM_DLC_CFC)?
669 error = sooptcopyout(sopt, &fcinfo, sizeof(fcinfo));
679 switch (sopt->sopt_name) {
691 mtx_unlock(&pcb->pcb_mtx);
694 } /* ng_btsocket_rfcomm_ctloutput */
697 * Detach and destroy socket
701 ng_btsocket_rfcomm_detach(struct socket *so)
703 ng_btsocket_rfcomm_pcb_p pcb = so2rfcomm_pcb(so);
705 KASSERT(pcb != NULL, ("ng_btsocket_rfcomm_detach: pcb == NULL"));
707 mtx_lock(&pcb->pcb_mtx);
709 switch (pcb->state) {
710 case NG_BTSOCKET_RFCOMM_DLC_W4_CONNECT:
711 case NG_BTSOCKET_RFCOMM_DLC_CONFIGURING:
712 case NG_BTSOCKET_RFCOMM_DLC_CONNECTING:
713 case NG_BTSOCKET_RFCOMM_DLC_CONNECTED:
714 /* XXX What to do with pending request? */
715 if (pcb->flags & NG_BTSOCKET_RFCOMM_DLC_TIMO)
716 ng_btsocket_rfcomm_untimeout(pcb);
718 if (pcb->state == NG_BTSOCKET_RFCOMM_DLC_W4_CONNECT)
719 pcb->flags |= NG_BTSOCKET_RFCOMM_DLC_DETACHED;
721 pcb->state = NG_BTSOCKET_RFCOMM_DLC_DISCONNECTING;
723 ng_btsocket_rfcomm_task_wakeup();
726 case NG_BTSOCKET_RFCOMM_DLC_DISCONNECTING:
727 ng_btsocket_rfcomm_task_wakeup();
731 while (pcb->state != NG_BTSOCKET_RFCOMM_DLC_CLOSED)
732 msleep(&pcb->state, &pcb->pcb_mtx, PZERO, "rf_det", 0);
734 if (pcb->session != NULL)
735 panic("%s: pcb->session != NULL\n", __func__);
736 if (pcb->flags & NG_BTSOCKET_RFCOMM_DLC_TIMO)
737 panic("%s: timeout on closed DLC, flags=%#x\n",
738 __func__, pcb->flags);
740 mtx_lock(&ng_btsocket_rfcomm_sockets_mtx);
741 LIST_REMOVE(pcb, next);
742 mtx_unlock(&ng_btsocket_rfcomm_sockets_mtx);
744 mtx_unlock(&pcb->pcb_mtx);
746 mtx_destroy(&pcb->pcb_mtx);
747 bzero(pcb, sizeof(*pcb));
748 FREE(pcb, M_NETGRAPH_BTSOCKET_RFCOMM);
750 soisdisconnected(so);
752 } /* ng_btsocket_rfcomm_detach */
759 ng_btsocket_rfcomm_disconnect(struct socket *so)
761 ng_btsocket_rfcomm_pcb_p pcb = so2rfcomm_pcb(so);
766 mtx_lock(&pcb->pcb_mtx);
768 if (pcb->state == NG_BTSOCKET_RFCOMM_DLC_DISCONNECTING) {
769 mtx_unlock(&pcb->pcb_mtx);
770 return (EINPROGRESS);
773 /* XXX What to do with pending request? */
774 if (pcb->flags & NG_BTSOCKET_RFCOMM_DLC_TIMO)
775 ng_btsocket_rfcomm_untimeout(pcb);
777 switch (pcb->state) {
778 case NG_BTSOCKET_RFCOMM_DLC_CONFIGURING: /* XXX can we get here? */
779 case NG_BTSOCKET_RFCOMM_DLC_CONNECTING: /* XXX can we get here? */
780 case NG_BTSOCKET_RFCOMM_DLC_CONNECTED:
783 * Just change DLC state and enqueue RFCOMM task. It will
784 * queue and send DISC on the DLC.
787 pcb->state = NG_BTSOCKET_RFCOMM_DLC_DISCONNECTING;
788 soisdisconnecting(so);
790 ng_btsocket_rfcomm_task_wakeup();
793 case NG_BTSOCKET_RFCOMM_DLC_CLOSED:
794 case NG_BTSOCKET_RFCOMM_DLC_W4_CONNECT:
798 panic("%s: Invalid DLC state=%d, flags=%#x\n",
799 __func__, pcb->state, pcb->flags);
803 mtx_unlock(&pcb->pcb_mtx);
806 } /* ng_btsocket_rfcomm_disconnect */
809 * Listen on socket. First call to listen() will create listening RFCOMM session
813 ng_btsocket_rfcomm_listen(struct socket *so, int backlog, struct thread *td)
815 ng_btsocket_rfcomm_pcb_p pcb = so2rfcomm_pcb(so), pcb1;
816 ng_btsocket_rfcomm_session_p s = NULL;
817 struct socket *l2so = NULL;
818 int error, socreate_error, usedchannels;
822 if (pcb->channel > 30)
823 return (EADDRNOTAVAIL);
827 mtx_lock(&pcb->pcb_mtx);
829 if (pcb->channel == 0) {
830 mtx_lock(&ng_btsocket_rfcomm_sockets_mtx);
832 LIST_FOREACH(pcb1, &ng_btsocket_rfcomm_sockets, next)
833 if (pcb1->channel != 0 &&
834 bcmp(&pcb1->src, &pcb->src, sizeof(pcb->src)) == 0)
835 usedchannels |= (1 << (pcb1->channel - 1));
837 for (pcb->channel = 30; pcb->channel > 0; pcb->channel --)
838 if (!(usedchannels & (1 << (pcb->channel - 1))))
841 if (pcb->channel == 0) {
842 mtx_unlock(&ng_btsocket_rfcomm_sockets_mtx);
843 mtx_unlock(&pcb->pcb_mtx);
845 return (EADDRNOTAVAIL);
848 mtx_unlock(&ng_btsocket_rfcomm_sockets_mtx);
851 mtx_unlock(&pcb->pcb_mtx);
854 * XXX FIXME - This is FUBAR. socreate() will call soalloc(1), i.e.
855 * soalloc() is allowed to sleep in MALLOC. This creates "could sleep"
856 * WITNESS warnings. To work around this problem we will create L2CAP
857 * socket first and then check if we actually need it. Note that we
858 * will not check for errors in socreate() because if we failed to
859 * create L2CAP socket at this point we still might have already open
863 socreate_error = socreate(PF_BLUETOOTH, &l2so, SOCK_SEQPACKET,
864 BLUETOOTH_PROTO_L2CAP, td->td_ucred, td);
867 * Transition the socket and session into the LISTENING state. Check
868 * for collisions first, as there can only be one.
870 mtx_lock(&ng_btsocket_rfcomm_sessions_mtx);
872 error = solisten_proto_check(so);
877 LIST_FOREACH(s, &ng_btsocket_rfcomm_sessions, next)
878 if (s->state == NG_BTSOCKET_RFCOMM_SESSION_LISTENING)
883 * We need to create default RFCOMM session. Check if we have
884 * L2CAP socket. If l2so == NULL then error has the error code
888 error = socreate_error;
893 * Create default listen RFCOMM session. The default RFCOMM
894 * session will listen on ANY address.
896 * XXX FIXME Note that currently there is no way to adjust MTU
897 * for the default session.
899 error = ng_btsocket_rfcomm_session_create(&s, l2so,
900 NG_HCI_BDADDR_ANY, NULL, td);
906 solisten_proto(so, backlog);
909 mtx_unlock(&ng_btsocket_rfcomm_sessions_mtx);
911 * If we still have an l2so reference here, it's unneeded, so release
917 } /* ng_btsocket_listen */
924 ng_btsocket_rfcomm_peeraddr(struct socket *so, struct sockaddr **nam)
926 ng_btsocket_rfcomm_pcb_p pcb = so2rfcomm_pcb(so);
927 struct sockaddr_rfcomm sa;
932 bcopy(&pcb->dst, &sa.rfcomm_bdaddr, sizeof(sa.rfcomm_bdaddr));
933 sa.rfcomm_channel = pcb->channel;
934 sa.rfcomm_len = sizeof(sa);
935 sa.rfcomm_family = AF_BLUETOOTH;
937 *nam = sodupsockaddr((struct sockaddr *) &sa, M_WAITOK | M_NULLOK);
939 return ((*nam == NULL)? ENOMEM : 0);
940 } /* ng_btsocket_rfcomm_peeraddr */
943 * Send data to socket
947 ng_btsocket_rfcomm_send(struct socket *so, int flags, struct mbuf *m,
948 struct sockaddr *nam, struct mbuf *control, struct thread *td)
950 ng_btsocket_rfcomm_pcb_t *pcb = so2rfcomm_pcb(so);
953 /* Check socket and input */
954 if (pcb == NULL || m == NULL || control != NULL) {
959 mtx_lock(&pcb->pcb_mtx);
961 /* Make sure DLC is connected */
962 if (pcb->state != NG_BTSOCKET_RFCOMM_DLC_CONNECTED) {
963 mtx_unlock(&pcb->pcb_mtx);
968 /* Put the packet on the socket's send queue and wakeup RFCOMM task */
969 sbappend(&pcb->so->so_snd, m);
972 if (!(pcb->flags & NG_BTSOCKET_RFCOMM_DLC_SENDING)) {
973 pcb->flags |= NG_BTSOCKET_RFCOMM_DLC_SENDING;
974 error = ng_btsocket_rfcomm_task_wakeup();
977 mtx_unlock(&pcb->pcb_mtx);
979 NG_FREE_M(m); /* checks for != NULL */
983 } /* ng_btsocket_rfcomm_send */
990 ng_btsocket_rfcomm_sockaddr(struct socket *so, struct sockaddr **nam)
992 ng_btsocket_rfcomm_pcb_p pcb = so2rfcomm_pcb(so);
993 struct sockaddr_rfcomm sa;
998 bcopy(&pcb->src, &sa.rfcomm_bdaddr, sizeof(sa.rfcomm_bdaddr));
999 sa.rfcomm_channel = pcb->channel;
1000 sa.rfcomm_len = sizeof(sa);
1001 sa.rfcomm_family = AF_BLUETOOTH;
1003 *nam = sodupsockaddr((struct sockaddr *) &sa, M_WAITOK | M_NULLOK);
1005 return ((*nam == NULL)? ENOMEM : 0);
1006 } /* ng_btsocket_rfcomm_sockaddr */
1009 * Upcall function for L2CAP sockets. Enqueue RFCOMM task.
1013 ng_btsocket_rfcomm_upcall(struct socket *so, void *arg, int waitflag)
1018 panic("%s: so == NULL\n", __func__);
1020 if ((error = ng_btsocket_rfcomm_task_wakeup()) != 0)
1021 NG_BTSOCKET_RFCOMM_ALERT(
1022 "%s: Could not enqueue RFCOMM task, error=%d\n", __func__, error);
1023 } /* ng_btsocket_rfcomm_upcall */
1026 * RFCOMM task. Will handle all RFCOMM sessions in one pass.
1027 * XXX FIXME does not scale very well
1031 ng_btsocket_rfcomm_sessions_task(void *ctx, int pending)
1033 ng_btsocket_rfcomm_session_p s = NULL, s_next = NULL;
1035 mtx_lock(&ng_btsocket_rfcomm_sessions_mtx);
1037 for (s = LIST_FIRST(&ng_btsocket_rfcomm_sessions); s != NULL; ) {
1038 mtx_lock(&s->session_mtx);
1039 s_next = LIST_NEXT(s, next);
1041 ng_btsocket_rfcomm_session_task(s);
1043 if (s->state == NG_BTSOCKET_RFCOMM_SESSION_CLOSED) {
1044 /* Unlink and clean the session */
1045 LIST_REMOVE(s, next);
1047 NG_BT_MBUFQ_DRAIN(&s->outq);
1048 if (!LIST_EMPTY(&s->dlcs))
1049 panic("%s: DLC list is not empty\n", __func__);
1051 /* Close L2CAP socket */
1052 s->l2so->so_upcallarg = NULL;
1053 s->l2so->so_upcall = NULL;
1054 SOCKBUF_LOCK(&s->l2so->so_rcv);
1055 s->l2so->so_rcv.sb_flags &= ~SB_UPCALL;
1056 SOCKBUF_UNLOCK(&s->l2so->so_rcv);
1057 SOCKBUF_LOCK(&s->l2so->so_snd);
1058 s->l2so->so_snd.sb_flags &= ~SB_UPCALL;
1059 SOCKBUF_UNLOCK(&s->l2so->so_snd);
1062 mtx_unlock(&s->session_mtx);
1064 mtx_destroy(&s->session_mtx);
1065 bzero(s, sizeof(*s));
1066 FREE(s, M_NETGRAPH_BTSOCKET_RFCOMM);
1068 mtx_unlock(&s->session_mtx);
1073 mtx_unlock(&ng_btsocket_rfcomm_sessions_mtx);
1074 } /* ng_btsocket_rfcomm_sessions_task */
1077 * Process RFCOMM session. Will handle all RFCOMM sockets in one pass.
1081 ng_btsocket_rfcomm_session_task(ng_btsocket_rfcomm_session_p s)
1083 mtx_assert(&s->session_mtx, MA_OWNED);
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);
1091 s->state = NG_BTSOCKET_RFCOMM_SESSION_CLOSED;
1092 ng_btsocket_rfcomm_session_clean(s);
1095 /* Now process upcall */
1097 /* Try to accept new L2CAP connection(s) */
1098 case NG_BTSOCKET_RFCOMM_SESSION_LISTENING:
1099 while (ng_btsocket_rfcomm_session_accept(s) == 0)
1103 /* Process the results of the L2CAP connect */
1104 case NG_BTSOCKET_RFCOMM_SESSION_CONNECTING:
1105 ng_btsocket_rfcomm_session_process_pcb(s);
1107 if (ng_btsocket_rfcomm_session_connect(s) != 0) {
1108 s->state = NG_BTSOCKET_RFCOMM_SESSION_CLOSED;
1109 ng_btsocket_rfcomm_session_clean(s);
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);
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);
1128 case NG_BTSOCKET_RFCOMM_SESSION_CLOSED:
1132 panic("%s: Invalid session state=%d, flags=%#x\n",
1133 __func__, s->state, s->flags);
1136 } /* ng_btsocket_rfcomm_session_task */
1139 * Process RFCOMM connection indicator. Caller must hold s->session_mtx
1142 static ng_btsocket_rfcomm_pcb_p
1143 ng_btsocket_rfcomm_connect_ind(ng_btsocket_rfcomm_session_p s, int channel)
1145 ng_btsocket_rfcomm_pcb_p pcb = NULL, pcb1 = NULL;
1146 ng_btsocket_l2cap_pcb_p l2pcb = NULL;
1147 struct socket *so1 = NULL;
1149 mtx_assert(&s->session_mtx, MA_OWNED);
1152 * Try to find RFCOMM socket that listens on given source address
1153 * and channel. This will return the best possible match.
1156 l2pcb = so2l2cap_pcb(s->l2so);
1157 pcb = ng_btsocket_rfcomm_pcb_listener(&l2pcb->src, channel);
1162 * Check the pending connections queue and if we have space then
1163 * create new socket and set proper source and destination address,
1167 mtx_lock(&pcb->pcb_mtx);
1169 if (pcb->so->so_qlen <= pcb->so->so_qlimit)
1170 so1 = sonewconn(pcb->so, 0);
1172 mtx_unlock(&pcb->pcb_mtx);
1178 * If we got here than we have created new socket. So complete the
1179 * connection. Set source and destination address from the session.
1182 pcb1 = so2rfcomm_pcb(so1);
1184 panic("%s: pcb1 == NULL\n", __func__);
1186 mtx_lock(&pcb1->pcb_mtx);
1188 bcopy(&l2pcb->src, &pcb1->src, sizeof(pcb1->src));
1189 bcopy(&l2pcb->dst, &pcb1->dst, sizeof(pcb1->dst));
1190 pcb1->channel = channel;
1192 /* Link new DLC to the session. We already hold s->session_mtx */
1193 LIST_INSERT_HEAD(&s->dlcs, pcb1, session_next);
1196 mtx_unlock(&pcb1->pcb_mtx);
1199 } /* ng_btsocket_rfcomm_connect_ind */
1202 * Process RFCOMM connect confirmation. Caller must hold s->session_mtx.
1206 ng_btsocket_rfcomm_connect_cfm(ng_btsocket_rfcomm_session_p s)
1208 ng_btsocket_rfcomm_pcb_p pcb = NULL, pcb_next = NULL;
1211 mtx_assert(&s->session_mtx, MA_OWNED);
1214 * Wake up all waiting sockets and send PN request for each of them.
1215 * Note that timeout already been set in ng_btsocket_rfcomm_connect()
1217 * Note: cannot use LIST_FOREACH because ng_btsocket_rfcomm_pcb_kill
1218 * will unlink DLC from the session
1221 for (pcb = LIST_FIRST(&s->dlcs); pcb != NULL; ) {
1222 mtx_lock(&pcb->pcb_mtx);
1223 pcb_next = LIST_NEXT(pcb, session_next);
1225 if (pcb->state == NG_BTSOCKET_RFCOMM_DLC_W4_CONNECT) {
1227 bcopy(&so2l2cap_pcb(s->l2so)->src, &pcb->src,
1230 error = ng_btsocket_rfcomm_send_pn(pcb);
1232 pcb->state = NG_BTSOCKET_RFCOMM_DLC_CONFIGURING;
1234 ng_btsocket_rfcomm_pcb_kill(pcb, error);
1237 mtx_unlock(&pcb->pcb_mtx);
1240 } /* ng_btsocket_rfcomm_connect_cfm */
1242 /*****************************************************************************
1243 *****************************************************************************
1245 *****************************************************************************
1246 *****************************************************************************/
1249 * Create new RFCOMM session. That function WILL NOT take ownership over l2so.
1250 * Caller MUST free l2so if function failed.
1254 ng_btsocket_rfcomm_session_create(ng_btsocket_rfcomm_session_p *sp,
1255 struct socket *l2so, bdaddr_p src, bdaddr_p dst,
1258 ng_btsocket_rfcomm_session_p s = NULL;
1259 struct sockaddr_l2cap l2sa;
1260 struct sockopt l2sopt;
1264 mtx_assert(&ng_btsocket_rfcomm_sessions_mtx, MA_OWNED);
1266 /* Allocate the RFCOMM session */
1267 MALLOC(s, ng_btsocket_rfcomm_session_p, sizeof(*s),
1268 M_NETGRAPH_BTSOCKET_RFCOMM, M_WAITOK | M_NULLOK | M_ZERO);
1273 s->mtu = RFCOMM_DEFAULT_MTU;
1275 s->state = NG_BTSOCKET_RFCOMM_SESSION_CLOSED;
1276 NG_BT_MBUFQ_INIT(&s->outq, ifqmaxlen);
1279 * XXX Mark session mutex as DUPOK to prevent "duplicated lock of
1280 * the same type" message. When accepting new L2CAP connection
1281 * ng_btsocket_rfcomm_session_accept() holds both session mutexes
1282 * for "old" (accepting) session and "new" (created) session.
1285 mtx_init(&s->session_mtx, "btsocks_rfcomm_session_mtx", NULL,
1288 LIST_INIT(&s->dlcs);
1290 /* Prepare L2CAP socket */
1291 l2so->so_upcallarg = NULL;
1292 l2so->so_upcall = ng_btsocket_rfcomm_upcall;
1293 SOCKBUF_LOCK(&l2so->so_rcv);
1294 l2so->so_rcv.sb_flags |= SB_UPCALL;
1295 SOCKBUF_UNLOCK(&l2so->so_rcv);
1296 SOCKBUF_LOCK(&l2so->so_snd);
1297 l2so->so_snd.sb_flags |= SB_UPCALL;
1298 SOCKBUF_UNLOCK(&l2so->so_snd);
1299 l2so->so_state |= SS_NBIO;
1302 mtx_lock(&s->session_mtx);
1305 * "src" == NULL and "dst" == NULL means just create session.
1306 * caller must do the rest
1309 if (src == NULL && dst == NULL)
1313 * Set incoming MTU on L2CAP socket. It is RFCOMM session default MTU
1314 * plus 5 bytes: RFCOMM frame header, one extra byte for length and one
1315 * extra byte for credits.
1318 mtu = s->mtu + sizeof(struct rfcomm_frame_hdr) + 1 + 1;
1320 l2sopt.sopt_dir = SOPT_SET;
1321 l2sopt.sopt_level = SOL_L2CAP;
1322 l2sopt.sopt_name = SO_L2CAP_IMTU;
1323 l2sopt.sopt_val = (void *) &mtu;
1324 l2sopt.sopt_valsize = sizeof(mtu);
1325 l2sopt.sopt_td = NULL;
1327 error = sosetopt(s->l2so, &l2sopt);
1331 /* Bind socket to "src" address */
1332 l2sa.l2cap_len = sizeof(l2sa);
1333 l2sa.l2cap_family = AF_BLUETOOTH;
1334 l2sa.l2cap_psm = (dst == NULL)? htole16(NG_L2CAP_PSM_RFCOMM) : 0;
1335 bcopy(src, &l2sa.l2cap_bdaddr, sizeof(l2sa.l2cap_bdaddr));
1337 error = sobind(s->l2so, (struct sockaddr *) &l2sa, td);
1341 /* If "dst" is not NULL then initiate connect(), otherwise listen() */
1344 s->state = NG_BTSOCKET_RFCOMM_SESSION_LISTENING;
1346 error = solisten(s->l2so, 10, td);
1350 s->flags = NG_BTSOCKET_RFCOMM_SESSION_INITIATOR;
1351 s->state = NG_BTSOCKET_RFCOMM_SESSION_CONNECTING;
1353 l2sa.l2cap_len = sizeof(l2sa);
1354 l2sa.l2cap_family = AF_BLUETOOTH;
1355 l2sa.l2cap_psm = htole16(NG_L2CAP_PSM_RFCOMM);
1356 bcopy(dst, &l2sa.l2cap_bdaddr, sizeof(l2sa.l2cap_bdaddr));
1358 error = soconnect(s->l2so, (struct sockaddr *) &l2sa, td);
1364 LIST_INSERT_HEAD(&ng_btsocket_rfcomm_sessions, s, next);
1367 mtx_unlock(&s->session_mtx);
1372 mtx_unlock(&s->session_mtx);
1374 /* Return L2CAP socket back to its original state */
1375 l2so->so_upcallarg = NULL;
1376 l2so->so_upcall = NULL;
1377 SOCKBUF_LOCK(&l2so->so_rcv);
1378 l2so->so_rcv.sb_flags &= ~SB_UPCALL;
1379 SOCKBUF_UNLOCK(&l2so->so_rcv);
1380 SOCKBUF_LOCK(&l2so->so_snd);
1381 l2so->so_snd.sb_flags &= ~SB_UPCALL;
1382 SOCKBUF_UNLOCK(&l2so->so_snd);
1383 l2so->so_state &= ~SS_NBIO;
1385 mtx_destroy(&s->session_mtx);
1386 bzero(s, sizeof(*s));
1387 FREE(s, M_NETGRAPH_BTSOCKET_RFCOMM);
1390 } /* ng_btsocket_rfcomm_session_create */
1393 * Process accept() on RFCOMM session
1394 * XXX FIXME locking for "l2so"?
1398 ng_btsocket_rfcomm_session_accept(ng_btsocket_rfcomm_session_p s0)
1400 struct socket *l2so = NULL;
1401 struct sockaddr_l2cap *l2sa = NULL;
1402 ng_btsocket_l2cap_pcb_t *l2pcb = NULL;
1403 ng_btsocket_rfcomm_session_p s = NULL;
1406 mtx_assert(&ng_btsocket_rfcomm_sessions_mtx, MA_OWNED);
1407 mtx_assert(&s0->session_mtx, MA_OWNED);
1409 /* Check if there is a complete L2CAP connection in the queue */
1410 if ((error = s0->l2so->so_error) != 0) {
1411 NG_BTSOCKET_RFCOMM_ERR(
1412 "%s: Could not accept connection on L2CAP socket, error=%d\n", __func__, error);
1413 s0->l2so->so_error = 0;
1419 if (TAILQ_EMPTY(&s0->l2so->so_comp)) {
1421 if (s0->l2so->so_rcv.sb_state & SBS_CANTRCVMORE)
1422 return (ECONNABORTED);
1423 return (EWOULDBLOCK);
1426 /* Accept incoming L2CAP connection */
1427 l2so = TAILQ_FIRST(&s0->l2so->so_comp);
1429 panic("%s: l2so == NULL\n", __func__);
1431 TAILQ_REMOVE(&s0->l2so->so_comp, l2so, so_list);
1432 s0->l2so->so_qlen --;
1433 l2so->so_qstate &= ~SQ_COMP;
1434 l2so->so_head = NULL;
1437 l2so->so_state |= SS_NBIO;
1441 error = soaccept(l2so, (struct sockaddr **) &l2sa);
1443 NG_BTSOCKET_RFCOMM_ERR(
1444 "%s: soaccept() on L2CAP socket failed, error=%d\n", __func__, error);
1451 * Check if there is already active RFCOMM session between two devices.
1452 * If so then close L2CAP connection. We only support one RFCOMM session
1453 * between each pair of devices. Note that here we assume session in any
1454 * state. The session even could be in the middle of disconnecting.
1457 l2pcb = so2l2cap_pcb(l2so);
1458 s = ng_btsocket_rfcomm_session_by_addr(&l2pcb->src, &l2pcb->dst);
1460 /* Create a new RFCOMM session */
1461 error = ng_btsocket_rfcomm_session_create(&s, l2so, NULL, NULL,
1462 curthread /* XXX */);
1464 mtx_lock(&s->session_mtx);
1467 s->state = NG_BTSOCKET_RFCOMM_SESSION_CONNECTED;
1470 * Adjust MTU on incomming connection. Reserve 5 bytes:
1471 * RFCOMM frame header, one extra byte for length and
1472 * one extra byte for credits.
1475 s->mtu = min(l2pcb->imtu, l2pcb->omtu) -
1476 sizeof(struct rfcomm_frame_hdr) - 1 - 1;
1478 mtx_unlock(&s->session_mtx);
1480 NG_BTSOCKET_RFCOMM_ALERT(
1481 "%s: Failed to create new RFCOMM session, error=%d\n", __func__, error);
1486 NG_BTSOCKET_RFCOMM_WARN(
1487 "%s: Rejecting duplicating RFCOMM session between src=%x:%x:%x:%x:%x:%x and " \
1488 "dst=%x:%x:%x:%x:%x:%x, state=%d, flags=%#x\n", __func__,
1489 l2pcb->src.b[5], l2pcb->src.b[4], l2pcb->src.b[3],
1490 l2pcb->src.b[2], l2pcb->src.b[1], l2pcb->src.b[0],
1491 l2pcb->dst.b[5], l2pcb->dst.b[4], l2pcb->dst.b[3],
1492 l2pcb->dst.b[2], l2pcb->dst.b[1], l2pcb->dst.b[0],
1493 s->state, s->flags);
1500 } /* ng_btsocket_rfcomm_session_accept */
1503 * Process connect() on RFCOMM session
1504 * XXX FIXME locking for "l2so"?
1508 ng_btsocket_rfcomm_session_connect(ng_btsocket_rfcomm_session_p s)
1510 ng_btsocket_l2cap_pcb_p l2pcb = so2l2cap_pcb(s->l2so);
1513 mtx_assert(&s->session_mtx, MA_OWNED);
1515 /* First check if connection has failed */
1516 if ((error = s->l2so->so_error) != 0) {
1517 s->l2so->so_error = 0;
1519 NG_BTSOCKET_RFCOMM_ERR(
1520 "%s: Could not connect RFCOMM session, error=%d, state=%d, flags=%#x\n",
1521 __func__, error, s->state, s->flags);
1526 /* Is connection still in progress? */
1527 if (s->l2so->so_state & SS_ISCONNECTING)
1531 * If we got here then we are connected. Send SABM on DLCI 0 to
1532 * open multiplexor channel.
1536 s->state = NG_BTSOCKET_RFCOMM_SESSION_CONNECTED;
1539 * Adjust MTU on outgoing connection. Reserve 5 bytes: RFCOMM
1540 * frame header, one extra byte for length and one extra byte
1544 s->mtu = min(l2pcb->imtu, l2pcb->omtu) -
1545 sizeof(struct rfcomm_frame_hdr) - 1 - 1;
1547 error = ng_btsocket_rfcomm_send_command(s,RFCOMM_FRAME_SABM,0);
1549 error = ng_btsocket_rfcomm_task_wakeup();
1553 }/* ng_btsocket_rfcomm_session_connect */
1556 * Receive data on RFCOMM session
1557 * XXX FIXME locking for "l2so"?
1561 ng_btsocket_rfcomm_session_receive(ng_btsocket_rfcomm_session_p s)
1563 struct mbuf *m = NULL;
1565 int more, flags, error;
1567 mtx_assert(&s->session_mtx, MA_OWNED);
1569 /* Can we read from the L2CAP socket? */
1570 if (!soreadable(s->l2so))
1573 /* First check for error on L2CAP socket */
1574 if ((error = s->l2so->so_error) != 0) {
1575 s->l2so->so_error = 0;
1577 NG_BTSOCKET_RFCOMM_ERR(
1578 "%s: Could not receive data from L2CAP socket, error=%d, state=%d, flags=%#x\n",
1579 __func__, error, s->state, s->flags);
1585 * Read all packets from the L2CAP socket.
1586 * XXX FIXME/VERIFY is that correct? For now use m->m_nextpkt as
1587 * indication that there is more packets on the socket's buffer.
1588 * Also what should we use in uio.uio_resid?
1589 * May be s->mtu + sizeof(struct rfcomm_frame_hdr) + 1 + 1?
1592 for (more = 1; more; ) {
1593 /* Try to get next packet from socket */
1594 bzero(&uio, sizeof(uio));
1595 /* uio.uio_td = NULL; */
1596 uio.uio_resid = 1000000000;
1597 flags = MSG_DONTWAIT;
1600 error = soreceive(s->l2so, NULL, &uio, &m, NULL, &flags);
1602 if (error == EWOULDBLOCK)
1603 return (0); /* XXX can happen? */
1605 NG_BTSOCKET_RFCOMM_ERR(
1606 "%s: Could not receive data from L2CAP socket, error=%d\n", __func__, error);
1611 more = (m->m_nextpkt != NULL);
1612 m->m_nextpkt = NULL;
1614 ng_btsocket_rfcomm_receive_frame(s, m);
1618 } /* ng_btsocket_rfcomm_session_receive */
1621 * Send data on RFCOMM session
1622 * XXX FIXME locking for "l2so"?
1626 ng_btsocket_rfcomm_session_send(ng_btsocket_rfcomm_session_p s)
1628 struct mbuf *m = NULL;
1631 mtx_assert(&s->session_mtx, MA_OWNED);
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;
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);
1646 NG_BT_MBUFQ_DEQUEUE(&s->outq, m);
1648 return (0); /* we are done */
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 */);
1654 NG_BTSOCKET_RFCOMM_ERR(
1655 "%s: Could not send data to L2CAP socket, error=%d\n", __func__, error);
1662 } /* ng_btsocket_rfcomm_session_send */
1665 * Close and disconnect all DLCs for the given session. Caller must hold
1666 * s->sesson_mtx. Will wakeup session.
1670 ng_btsocket_rfcomm_session_clean(ng_btsocket_rfcomm_session_p s)
1672 ng_btsocket_rfcomm_pcb_p pcb = NULL, pcb_next = NULL;
1675 mtx_assert(&s->session_mtx, MA_OWNED);
1678 * Note: cannot use LIST_FOREACH because ng_btsocket_rfcomm_pcb_kill
1679 * will unlink DLC from the session
1682 for (pcb = LIST_FIRST(&s->dlcs); pcb != NULL; ) {
1683 mtx_lock(&pcb->pcb_mtx);
1684 pcb_next = LIST_NEXT(pcb, session_next);
1686 NG_BTSOCKET_RFCOMM_INFO(
1687 "%s: Disconnecting dlci=%d, state=%d, flags=%#x\n",
1688 __func__, pcb->dlci, pcb->state, pcb->flags);
1690 if (pcb->state == NG_BTSOCKET_RFCOMM_DLC_CONNECTED)
1693 error = ECONNREFUSED;
1695 ng_btsocket_rfcomm_pcb_kill(pcb, error);
1697 mtx_unlock(&pcb->pcb_mtx);
1700 } /* ng_btsocket_rfcomm_session_clean */
1703 * Process all DLCs on the session. Caller MUST hold s->session_mtx.
1707 ng_btsocket_rfcomm_session_process_pcb(ng_btsocket_rfcomm_session_p s)
1709 ng_btsocket_rfcomm_pcb_p pcb = NULL, pcb_next = NULL;
1712 mtx_assert(&s->session_mtx, MA_OWNED);
1715 * Note: cannot use LIST_FOREACH because ng_btsocket_rfcomm_pcb_kill
1716 * will unlink DLC from the session
1719 for (pcb = LIST_FIRST(&s->dlcs); pcb != NULL; ) {
1720 mtx_lock(&pcb->pcb_mtx);
1721 pcb_next = LIST_NEXT(pcb, session_next);
1723 switch (pcb->state) {
1726 * If DLC in W4_CONNECT state then we should check for both
1727 * timeout and detach.
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);
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.
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);
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).
1755 * XXX FIXME need scheduler for RFCOMM sockets
1758 case NG_BTSOCKET_RFCOMM_DLC_CONNECTED:
1759 error = ng_btsocket_rfcomm_pcb_send(pcb, ALOT);
1761 ng_btsocket_rfcomm_pcb_kill(pcb, error);
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.
1769 * XXX FIXME need to drain all data from the socket's queue
1770 * if LINGER option was set
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,
1779 ng_btsocket_rfcomm_timeout(pcb);
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);
1786 /* case NG_BTSOCKET_RFCOMM_DLC_CLOSED: */
1788 panic("%s: Invalid DLC state=%d, flags=%#x\n",
1789 __func__, pcb->state, pcb->flags);
1793 mtx_unlock(&pcb->pcb_mtx);
1796 } /* ng_btsocket_rfcomm_session_process_pcb */
1799 * Find RFCOMM session between "src" and "dst".
1800 * Caller MUST hold ng_btsocket_rfcomm_sessions_mtx.
1803 static ng_btsocket_rfcomm_session_p
1804 ng_btsocket_rfcomm_session_by_addr(bdaddr_p src, bdaddr_p dst)
1806 ng_btsocket_rfcomm_session_p s = NULL;
1807 ng_btsocket_l2cap_pcb_p l2pcb = NULL;
1810 mtx_assert(&ng_btsocket_rfcomm_sessions_mtx, MA_OWNED);
1812 any_src = (bcmp(src, NG_HCI_BDADDR_ANY, sizeof(*src)) == 0);
1814 LIST_FOREACH(s, &ng_btsocket_rfcomm_sessions, next) {
1815 l2pcb = so2l2cap_pcb(s->l2so);
1817 if ((any_src || bcmp(&l2pcb->src, src, sizeof(*src)) == 0) &&
1818 bcmp(&l2pcb->dst, dst, sizeof(*dst)) == 0)
1823 } /* ng_btsocket_rfcomm_session_by_addr */
1825 /*****************************************************************************
1826 *****************************************************************************
1828 *****************************************************************************
1829 *****************************************************************************/
1832 * Process incoming RFCOMM frame. Caller must hold s->session_mtx.
1833 * XXX FIXME check frame length
1837 ng_btsocket_rfcomm_receive_frame(ng_btsocket_rfcomm_session_p s,
1840 struct rfcomm_frame_hdr *hdr = NULL;
1841 struct mbuf *m = NULL;
1843 u_int8_t dlci, type;
1846 mtx_assert(&s->session_mtx, MA_OWNED);
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);
1859 hdr = mtod(m0, struct rfcomm_frame_hdr *);
1860 dlci = RFCOMM_DLCI(hdr->address);
1861 type = RFCOMM_TYPE(hdr->control);
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);
1869 length = hdr->length >> 1;
1870 m_adj(m0, sizeof(*hdr));
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);
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 :)
1884 for (m = m0; m->m_next != NULL; m = m->m_next)
1887 panic("%s: Empty mbuf at the end of the chain, len=%d\n",
1888 __func__, m->m_len);
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.
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__);
1903 m_adj(m0, -1); /* Trim FCS byte */
1906 * Process RFCOMM frame.
1908 * From TS 07.10 spec
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..."
1913 * "... If a unsolicited DM response is received then the frame shall
1914 * be processed irrespective of the P/F setting... "
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..."
1921 * From Bluetooth spec
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..."
1929 case RFCOMM_FRAME_SABM:
1930 if (RFCOMM_PF(hdr->control))
1931 error = ng_btsocket_rfcomm_receive_sabm(s, dlci);
1934 case RFCOMM_FRAME_DISC:
1935 if (RFCOMM_PF(hdr->control))
1936 error = ng_btsocket_rfcomm_receive_disc(s, dlci);
1939 case RFCOMM_FRAME_UA:
1940 if (RFCOMM_PF(hdr->control))
1941 error = ng_btsocket_rfcomm_receive_ua(s, dlci);
1944 case RFCOMM_FRAME_DM:
1945 error = ng_btsocket_rfcomm_receive_dm(s, dlci);
1948 case RFCOMM_FRAME_UIH:
1950 error = ng_btsocket_rfcomm_receive_mcc(s, m0);
1952 error = ng_btsocket_rfcomm_receive_uih(s, dlci,
1953 RFCOMM_PF(hdr->control), m0);
1959 NG_BTSOCKET_RFCOMM_ERR(
1960 "%s: Invalid RFCOMM packet. Unknown type=%#x\n", __func__, type);
1968 } /* ng_btsocket_rfcomm_receive_frame */
1971 * Process RFCOMM SABM frame
1975 ng_btsocket_rfcomm_receive_sabm(ng_btsocket_rfcomm_session_p s, int dlci)
1977 ng_btsocket_rfcomm_pcb_p pcb = NULL;
1980 mtx_assert(&s->session_mtx, MA_OWNED);
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);
1986 /* DLCI == 0 means open multiplexor channel */
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);
1994 s->state = NG_BTSOCKET_RFCOMM_SESSION_OPEN;
1995 ng_btsocket_rfcomm_connect_cfm(s);
1997 s->state = NG_BTSOCKET_RFCOMM_SESSION_CLOSED;
1998 ng_btsocket_rfcomm_session_clean(s);
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);
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);
2023 * Check if we have this DLCI. This might happen when remote
2024 * peer uses PN command before actual open (SABM) happens.
2027 pcb = ng_btsocket_rfcomm_pcb_by_dlci(s, dlci);
2029 mtx_lock(&pcb->pcb_mtx);
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);
2040 ng_btsocket_rfcomm_untimeout(pcb);
2042 error = ng_btsocket_rfcomm_send_command(s,RFCOMM_FRAME_UA,dlci);
2044 error = ng_btsocket_rfcomm_send_msc(pcb);
2047 pcb->state = NG_BTSOCKET_RFCOMM_DLC_CONNECTED;
2048 soisconnected(pcb->so);
2050 ng_btsocket_rfcomm_pcb_kill(pcb, error);
2052 mtx_unlock(&pcb->pcb_mtx);
2058 * We do not have requested DLCI, so it must be an incoming connection
2059 * with default parameters. Try to accept it.
2062 pcb = ng_btsocket_rfcomm_connect_ind(s, RFCOMM_SRVCHANNEL(dlci));
2064 mtx_lock(&pcb->pcb_mtx);
2068 error = ng_btsocket_rfcomm_send_command(s,RFCOMM_FRAME_UA,dlci);
2070 error = ng_btsocket_rfcomm_send_msc(pcb);
2073 pcb->state = NG_BTSOCKET_RFCOMM_DLC_CONNECTED;
2074 soisconnected(pcb->so);
2076 ng_btsocket_rfcomm_pcb_kill(pcb, error);
2078 mtx_unlock(&pcb->pcb_mtx);
2080 /* Nobody is listen()ing on the requested DLCI */
2081 error = ng_btsocket_rfcomm_send_command(s,RFCOMM_FRAME_DM,dlci);
2084 } /* ng_btsocket_rfcomm_receive_sabm */
2087 * Process RFCOMM DISC frame
2091 ng_btsocket_rfcomm_receive_disc(ng_btsocket_rfcomm_session_p s, int dlci)
2093 ng_btsocket_rfcomm_pcb_p pcb = NULL;
2096 mtx_assert(&s->session_mtx, MA_OWNED);
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);
2102 /* DLCI == 0 means close multiplexor channel */
2104 /* XXX FIXME assume that remote side will close the socket */
2105 error = ng_btsocket_rfcomm_send_command(s, RFCOMM_FRAME_UA, 0);
2107 if (s->state == NG_BTSOCKET_RFCOMM_SESSION_DISCONNECTING)
2108 s->state = NG_BTSOCKET_RFCOMM_SESSION_CLOSED; /* XXX */
2110 s->state = NG_BTSOCKET_RFCOMM_SESSION_DISCONNECTING;
2112 s->state = NG_BTSOCKET_RFCOMM_SESSION_CLOSED; /* XXX */
2114 ng_btsocket_rfcomm_session_clean(s);
2116 pcb = ng_btsocket_rfcomm_pcb_by_dlci(s, dlci);
2120 mtx_lock(&pcb->pcb_mtx);
2122 NG_BTSOCKET_RFCOMM_INFO(
2123 "%s: Got DISC for dlci=%d, state=%d, flags=%#x\n",
2124 __func__, dlci, pcb->state, pcb->flags);
2126 error = ng_btsocket_rfcomm_send_command(s,
2127 RFCOMM_FRAME_UA, dlci);
2129 if (pcb->state == NG_BTSOCKET_RFCOMM_DLC_CONNECTED)
2134 ng_btsocket_rfcomm_pcb_kill(pcb, err);
2136 mtx_unlock(&pcb->pcb_mtx);
2138 NG_BTSOCKET_RFCOMM_WARN(
2139 "%s: Got DISC for non-existing dlci=%d\n", __func__, dlci);
2141 error = ng_btsocket_rfcomm_send_command(s,
2142 RFCOMM_FRAME_DM, dlci);
2147 } /* ng_btsocket_rfcomm_receive_disc */
2150 * Process RFCOMM UA frame
2154 ng_btsocket_rfcomm_receive_ua(ng_btsocket_rfcomm_session_p s, int dlci)
2156 ng_btsocket_rfcomm_pcb_p pcb = NULL;
2159 mtx_assert(&s->session_mtx, MA_OWNED);
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);
2165 /* dlci == 0 means multiplexor channel */
2168 case NG_BTSOCKET_RFCOMM_SESSION_CONNECTED:
2169 s->state = NG_BTSOCKET_RFCOMM_SESSION_OPEN;
2170 ng_btsocket_rfcomm_connect_cfm(s);
2173 case NG_BTSOCKET_RFCOMM_SESSION_DISCONNECTING:
2174 s->state = NG_BTSOCKET_RFCOMM_SESSION_CLOSED;
2175 ng_btsocket_rfcomm_session_clean(s);
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,
2190 /* Check if we have this DLCI */
2191 pcb = ng_btsocket_rfcomm_pcb_by_dlci(s, dlci);
2193 mtx_lock(&pcb->pcb_mtx);
2195 NG_BTSOCKET_RFCOMM_INFO(
2196 "%s: Got UA for dlci=%d, state=%d, flags=%#x\n",
2197 __func__, dlci, pcb->state, pcb->flags);
2199 switch (pcb->state) {
2200 case NG_BTSOCKET_RFCOMM_DLC_CONNECTING:
2201 ng_btsocket_rfcomm_untimeout(pcb);
2203 error = ng_btsocket_rfcomm_send_msc(pcb);
2205 pcb->state = NG_BTSOCKET_RFCOMM_DLC_CONNECTED;
2206 soisconnected(pcb->so);
2210 case NG_BTSOCKET_RFCOMM_DLC_DISCONNECTING:
2211 ng_btsocket_rfcomm_pcb_kill(pcb, 0);
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);
2222 mtx_unlock(&pcb->pcb_mtx);
2224 NG_BTSOCKET_RFCOMM_WARN(
2225 "%s: Got UA for non-existing dlci=%d\n", __func__, dlci);
2227 error = ng_btsocket_rfcomm_send_command(s,RFCOMM_FRAME_DM,dlci);
2231 } /* ng_btsocket_rfcomm_receive_ua */
2234 * Process RFCOMM DM frame
2238 ng_btsocket_rfcomm_receive_dm(ng_btsocket_rfcomm_session_p s, int dlci)
2240 ng_btsocket_rfcomm_pcb_p pcb = NULL;
2243 mtx_assert(&s->session_mtx, MA_OWNED);
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);
2249 /* DLCI == 0 means multiplexor channel */
2251 /* Disconnect all dlc's on the session */
2252 s->state = NG_BTSOCKET_RFCOMM_SESSION_CLOSED;
2253 ng_btsocket_rfcomm_session_clean(s);
2255 pcb = ng_btsocket_rfcomm_pcb_by_dlci(s, dlci);
2257 mtx_lock(&pcb->pcb_mtx);
2259 NG_BTSOCKET_RFCOMM_INFO(
2260 "%s: Got DM for dlci=%d, state=%d, flags=%#x\n",
2261 __func__, dlci, pcb->state, pcb->flags);
2263 if (pcb->state == NG_BTSOCKET_RFCOMM_DLC_CONNECTED)
2266 error = ECONNREFUSED;
2268 ng_btsocket_rfcomm_pcb_kill(pcb, error);
2270 mtx_unlock(&pcb->pcb_mtx);
2272 NG_BTSOCKET_RFCOMM_WARN(
2273 "%s: Got DM for non-existing dlci=%d\n", __func__, dlci);
2277 } /* ng_btsocket_rfcomm_receive_dm */
2280 * Process RFCOMM UIH frame (data)
2284 ng_btsocket_rfcomm_receive_uih(ng_btsocket_rfcomm_session_p s, int dlci,
2285 int pf, struct mbuf *m0)
2287 ng_btsocket_rfcomm_pcb_p pcb = NULL;
2290 mtx_assert(&s->session_mtx, MA_OWNED);
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,
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);
2305 /* Check if we have this dlci */
2306 pcb = ng_btsocket_rfcomm_pcb_by_dlci(s, dlci);
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);
2314 mtx_lock(&pcb->pcb_mtx);
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);
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);
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);
2344 pcb->tx_cred += *mtod(m0, u_int8_t *);
2347 /* Send more from the DLC. XXX check for errors? */
2348 ng_btsocket_rfcomm_pcb_send(pcb, ALOT);
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);
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);
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);
2373 } else if (m0->m_pkthdr.len > sbspace(&pcb->so->so_rcv)) {
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.
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));
2389 /* Append packet to the socket receive queue */
2390 sbappend(&pcb->so->so_rcv, m0);
2397 mtx_unlock(&pcb->pcb_mtx);
2399 NG_FREE_M(m0); /* checks for != NULL */
2402 } /* ng_btsocket_rfcomm_receive_uih */
2405 * Process RFCOMM MCC command (Multiplexor)
2407 * From TS 07.10 spec
2409 * "5.4.3.1 Information Data
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..."
2414 * "5.4.6.2 Operating procedures
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...
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."
2430 ng_btsocket_rfcomm_receive_mcc(ng_btsocket_rfcomm_session_p s, struct mbuf *m0)
2432 struct rfcomm_mcc_hdr *hdr = NULL;
2433 u_int8_t cr, type, length;
2435 mtx_assert(&s->session_mtx, MA_OWNED);
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).
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);
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);
2459 case RFCOMM_MCC_TEST:
2460 return (ng_btsocket_rfcomm_receive_test(s, m0));
2463 case RFCOMM_MCC_FCON:
2464 case RFCOMM_MCC_FCOFF:
2465 return (ng_btsocket_rfcomm_receive_fc(s, m0));
2468 case RFCOMM_MCC_MSC:
2469 return (ng_btsocket_rfcomm_receive_msc(s, m0));
2472 case RFCOMM_MCC_RPN:
2473 return (ng_btsocket_rfcomm_receive_rpn(s, m0));
2476 case RFCOMM_MCC_RLS:
2477 return (ng_btsocket_rfcomm_receive_rls(s, m0));
2481 return (ng_btsocket_rfcomm_receive_pn(s, m0));
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);
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);
2499 /* Reuse mbuf to send NSC */
2500 hdr = mtod(m0, struct rfcomm_mcc_hdr *);
2501 m0->m_pkthdr.len = m0->m_len = sizeof(*hdr);
2503 /* Create MCC NSC header */
2504 hdr->type = RFCOMM_MKMCC_TYPE(0, RFCOMM_MCC_NSC);
2505 hdr->length = RFCOMM_MKLEN8(1);
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 ++;
2512 /* Send UIH frame */
2513 return (ng_btsocket_rfcomm_send_uih(s,
2514 RFCOMM_MKADDRESS(INITIATOR(s), 0), 0, 0, m0));
2519 } /* ng_btsocket_rfcomm_receive_mcc */
2522 * Receive RFCOMM TEST MCC command
2526 ng_btsocket_rfcomm_receive_test(ng_btsocket_rfcomm_session_p s, struct mbuf *m0)
2528 struct rfcomm_mcc_hdr *hdr = mtod(m0, struct rfcomm_mcc_hdr *);
2531 mtx_assert(&s->session_mtx, MA_OWNED);
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);
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);
2543 NG_FREE_M(m0); /* XXX ignore response */
2546 } /* ng_btsocket_rfcomm_receive_test */
2549 * Receive RFCOMM FCON/FCOFF MCC command
2553 ng_btsocket_rfcomm_receive_fc(ng_btsocket_rfcomm_session_p s, struct mbuf *m0)
2555 struct rfcomm_mcc_hdr *hdr = mtod(m0, struct rfcomm_mcc_hdr *);
2556 u_int8_t type = RFCOMM_MCC_TYPE(hdr->type);
2559 mtx_assert(&s->session_mtx, MA_OWNED);
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).
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);
2573 if (RFCOMM_CR(hdr->type)) {
2574 if (type == RFCOMM_MCC_FCON)
2575 s->flags &= ~NG_BTSOCKET_RFCOMM_SESSION_RFC;
2577 s->flags |= NG_BTSOCKET_RFCOMM_SESSION_RFC;
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);
2583 NG_FREE_M(m0); /* XXX ignore response */
2586 } /* ng_btsocket_rfcomm_receive_fc */
2589 * Receive RFCOMM MSC MCC command
2593 ng_btsocket_rfcomm_receive_msc(ng_btsocket_rfcomm_session_p s, struct mbuf *m0)
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;
2600 mtx_assert(&s->session_mtx, MA_OWNED);
2602 NG_BTSOCKET_RFCOMM_INFO(
2603 "%s: Got MCC MSC, dlci=%d, cr=%d, length=%d, session state=%d, flags=%#x, " \
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);
2609 if (RFCOMM_CR(hdr->type)) {
2610 pcb = ng_btsocket_rfcomm_pcb_by_dlci(s, RFCOMM_DLCI(msc->address));
2612 NG_BTSOCKET_RFCOMM_WARN(
2613 "%s: Got MSC command for non-existing dlci=%d\n",
2614 __func__, RFCOMM_DLCI(msc->address));
2620 mtx_lock(&pcb->pcb_mtx);
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),
2629 mtx_unlock(&pcb->pcb_mtx);
2635 pcb->rmodem = msc->modem; /* Update remote port signals */
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);
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);
2648 mtx_unlock(&pcb->pcb_mtx);
2650 NG_FREE_M(m0); /* XXX ignore response */
2653 } /* ng_btsocket_rfcomm_receive_msc */
2656 * Receive RFCOMM RPN MCC command
2657 * XXX FIXME do we need htole16/le16toh for RPN param_mask?
2661 ng_btsocket_rfcomm_receive_rpn(ng_btsocket_rfcomm_session_p s, struct mbuf *m0)
2663 struct rfcomm_mcc_hdr *hdr = mtod(m0, struct rfcomm_mcc_hdr *);
2664 struct rfcomm_mcc_rpn *rpn = (struct rfcomm_mcc_rpn *)(hdr + 1);
2666 u_int16_t param_mask;
2667 u_int8_t bit_rate, data_bits, stop_bits, parity,
2668 flow_control, xon_char, xoff_char;
2670 mtx_assert(&s->session_mtx, MA_OWNED);
2672 NG_BTSOCKET_RFCOMM_INFO(
2673 "%s: Got MCC RPN, dlci=%d, cr=%d, length=%d, session state=%d, flags=%#x, " \
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);
2679 if (RFCOMM_CR(hdr->type)) {
2680 param_mask = RFCOMM_RPN_PM_ALL;
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;
2693 * Ignore/accept bit_rate, 8 bits, 1 stop bit, no
2694 * parity, no flow control lines, default XON/XOFF
2698 bit_rate = rpn->bit_rate;
2699 rpn->param_mask = le16toh(rpn->param_mask); /* XXX */
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;
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;
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;
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;
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;
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;
2744 rpn->bit_rate = bit_rate;
2745 rpn->line_settings = RFCOMM_MKRPN_LINE_SETTINGS(data_bits,
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 */
2752 m0->m_pkthdr.len = m0->m_len = sizeof(*hdr) + sizeof(*rpn);
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);
2758 NG_FREE_M(m0); /* XXX ignore response */
2761 } /* ng_btsocket_rfcomm_receive_rpn */
2764 * Receive RFCOMM RLS MCC command
2768 ng_btsocket_rfcomm_receive_rls(ng_btsocket_rfcomm_session_p s, struct mbuf *m0)
2770 struct rfcomm_mcc_hdr *hdr = mtod(m0, struct rfcomm_mcc_hdr *);
2771 struct rfcomm_mcc_rls *rls = (struct rfcomm_mcc_rls *)(hdr + 1);
2774 mtx_assert(&s->session_mtx, MA_OWNED);
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.
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);
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),
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);
2799 NG_FREE_M(m0); /* XXX ignore responses */
2802 } /* ng_btsocket_rfcomm_receive_rls */
2805 * Receive RFCOMM PN MCC command
2809 ng_btsocket_rfcomm_receive_pn(ng_btsocket_rfcomm_session_p s, struct mbuf *m0)
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;
2816 mtx_assert(&s->session_mtx, MA_OWNED);
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);
2827 if (pn->dlci == 0) {
2828 NG_BTSOCKET_RFCOMM_ERR("%s: Zero dlci in MCC PN\n", __func__);
2834 /* Check if we have this dlci */
2835 pcb = ng_btsocket_rfcomm_pcb_by_dlci(s, pn->dlci);
2837 mtx_lock(&pcb->pcb_mtx);
2839 if (RFCOMM_CR(hdr->type)) {
2841 ng_btsocket_rfcomm_set_pn(pcb, 1, pn->flow_control,
2842 pn->credits, pn->mtu);
2844 if (pcb->flags & NG_BTSOCKET_RFCOMM_DLC_CFC) {
2845 pn->flow_control = 0xe0;
2846 pn->credits = RFCOMM_DEFAULT_CREDITS;
2848 pn->flow_control = 0;
2852 hdr->type = RFCOMM_MKMCC_TYPE(0, RFCOMM_MCC_PN);
2853 error = ng_btsocket_rfcomm_send_uih(s,
2854 RFCOMM_MKADDRESS(INITIATOR(s), 0),
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);
2862 pcb->state = NG_BTSOCKET_RFCOMM_DLC_CONNECTING;
2863 error = ng_btsocket_rfcomm_send_command(s,
2864 RFCOMM_FRAME_SABM, pn->dlci);
2866 NG_BTSOCKET_RFCOMM_WARN(
2867 "%s: Got PN response for dlci=%d in invalid state=%d\n",
2868 __func__, pn->dlci, pcb->state);
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));
2879 mtx_lock(&pcb->pcb_mtx);
2881 pcb->dlci = pn->dlci;
2883 ng_btsocket_rfcomm_set_pn(pcb, 1, pn->flow_control,
2884 pn->credits, pn->mtu);
2886 if (pcb->flags & NG_BTSOCKET_RFCOMM_DLC_CFC) {
2887 pn->flow_control = 0xe0;
2888 pn->credits = RFCOMM_DEFAULT_CREDITS;
2890 pn->flow_control = 0;
2894 hdr->type = RFCOMM_MKMCC_TYPE(0, RFCOMM_MCC_PN);
2895 error = ng_btsocket_rfcomm_send_uih(s,
2896 RFCOMM_MKADDRESS(INITIATOR(s), 0),
2900 ng_btsocket_rfcomm_timeout(pcb);
2901 pcb->state = NG_BTSOCKET_RFCOMM_DLC_CONNECTING;
2902 soisconnecting(pcb->so);
2904 ng_btsocket_rfcomm_pcb_kill(pcb, error);
2906 mtx_unlock(&pcb->pcb_mtx);
2908 /* Nobody is listen()ing on this channel */
2909 error = ng_btsocket_rfcomm_send_command(s,
2910 RFCOMM_FRAME_DM, pn->dlci);
2914 NG_FREE_M(m0); /* XXX ignore response to non-existing dlci */
2917 } /* ng_btsocket_rfcomm_receive_pn */
2920 * Set PN parameters for dlci. Caller must hold pcb->pcb_mtx.
2922 * From Bluetooth spec.
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).
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..."
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)
2945 mtx_assert(&pcb->pcb_mtx, MA_OWNED);
2947 pcb->mtu = le16toh(mtu);
2950 if (flow_control == 0xf0) {
2951 pcb->flags |= NG_BTSOCKET_RFCOMM_DLC_CFC;
2952 pcb->tx_cred = credits;
2954 pcb->flags &= ~NG_BTSOCKET_RFCOMM_DLC_CFC;
2958 if (flow_control == 0xe0) {
2959 pcb->flags |= NG_BTSOCKET_RFCOMM_DLC_CFC;
2960 pcb->tx_cred = credits;
2962 pcb->flags &= ~NG_BTSOCKET_RFCOMM_DLC_CFC;
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 */
2974 * Send RFCOMM SABM/DISC/UA/DM frames. Caller must hold s->session_mtx
2978 ng_btsocket_rfcomm_send_command(ng_btsocket_rfcomm_session_p s,
2979 u_int8_t type, u_int8_t dlci)
2981 struct rfcomm_cmd_hdr *hdr = NULL;
2982 struct mbuf *m = NULL;
2985 mtx_assert(&s->session_mtx, MA_OWNED);
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);
2992 case RFCOMM_FRAME_SABM:
2993 case RFCOMM_FRAME_DISC:
2997 case RFCOMM_FRAME_UA:
2998 case RFCOMM_FRAME_DM:
3003 panic("%s: Invalid frame type=%#x\n", __func__, type);
3008 MGETHDR(m, MB_DONTWAIT, MT_DATA);
3012 m->m_pkthdr.len = m->m_len = sizeof(*hdr);
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);
3020 NG_BT_MBUFQ_ENQUEUE(&s->outq, m);
3023 } /* ng_btsocket_rfcomm_send_command */
3026 * Send RFCOMM UIH frame. Caller must hold s->session_mtx
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)
3033 struct rfcomm_frame_hdr *hdr = NULL;
3034 struct mbuf *m = NULL, *mcrc = NULL;
3037 mtx_assert(&s->session_mtx, MA_OWNED);
3039 MGETHDR(m, MB_DONTWAIT, MT_DATA);
3044 m->m_pkthdr.len = m->m_len = sizeof(*hdr);
3046 MGET(mcrc, MB_DONTWAIT, MT_DATA);
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);
3059 mcrc->m_data[0] = ng_btsocket_rfcomm_fcs2((u_int8_t *) hdr);
3061 /* Put length back */
3062 length = (data != NULL)? data->m_pkthdr.len : 0;
3064 u_int16_t l = htole16(RFCOMM_MKLEN16(length));
3066 bcopy(&l, &hdr->length, sizeof(l));
3070 hdr->length = RFCOMM_MKLEN8(length);
3073 m->m_data[m->m_len] = credits;
3081 m->m_pkthdr.len += length;
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,
3094 NG_BT_MBUFQ_ENQUEUE(&s->outq, m);
3097 } /* ng_btsocket_rfcomm_send_uih */
3100 * Send MSC request. Caller must hold pcb->pcb_mtx and pcb->session->session_mtx
3104 ng_btsocket_rfcomm_send_msc(ng_btsocket_rfcomm_pcb_p pcb)
3106 struct mbuf *m = NULL;
3107 struct rfcomm_mcc_hdr *hdr = NULL;
3108 struct rfcomm_mcc_msc *msc = NULL;
3110 mtx_assert(&pcb->session->session_mtx, MA_OWNED);
3111 mtx_assert(&pcb->pcb_mtx, MA_OWNED);
3113 MGETHDR(m, MB_DONTWAIT, MT_DATA);
3117 m->m_pkthdr.len = m->m_len = sizeof(*hdr) + sizeof(*msc);
3119 hdr = mtod(m, struct rfcomm_mcc_hdr *);
3120 msc = (struct rfcomm_mcc_msc *)(hdr + 1);
3122 hdr->type = RFCOMM_MKMCC_TYPE(1, RFCOMM_MCC_MSC);
3123 hdr->length = RFCOMM_MKLEN8(sizeof(*msc));
3125 msc->address = RFCOMM_MKADDRESS(1, pcb->dlci);
3126 msc->modem = pcb->lmodem;
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,
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 */
3138 * Send PN request. Caller must hold pcb->pcb_mtx and pcb->session->session_mtx
3142 ng_btsocket_rfcomm_send_pn(ng_btsocket_rfcomm_pcb_p pcb)
3144 struct mbuf *m = NULL;
3145 struct rfcomm_mcc_hdr *hdr = NULL;
3146 struct rfcomm_mcc_pn *pn = NULL;
3148 mtx_assert(&pcb->session->session_mtx, MA_OWNED);
3149 mtx_assert(&pcb->pcb_mtx, MA_OWNED);
3151 MGETHDR(m, MB_DONTWAIT, MT_DATA);
3155 m->m_pkthdr.len = m->m_len = sizeof(*hdr) + sizeof(*pn);
3157 hdr = mtod(m, struct rfcomm_mcc_hdr *);
3158 pn = (struct rfcomm_mcc_pn *)(hdr + 1);
3160 hdr->type = RFCOMM_MKMCC_TYPE(1, RFCOMM_MCC_PN);
3161 hdr->length = RFCOMM_MKLEN8(sizeof(*pn));
3163 pn->dlci = pcb->dlci;
3166 * Set default DLCI priority as described in GSM 07.10
3167 * (ETSI TS 101 369) clause 5.6 page 42
3170 pn->priority = (pcb->dlci < 56)? (((pcb->dlci >> 3) << 3) + 7) : 61;
3172 pn->mtu = htole16(pcb->mtu);
3173 pn->max_retrans = 0;
3175 if (pcb->flags & NG_BTSOCKET_RFCOMM_DLC_CFC) {
3176 pn->flow_control = 0xf0;
3177 pn->credits = pcb->rx_cred;
3179 pn->flow_control = 0;
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);
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 */
3193 * Calculate and send credits based on available space in receive buffer
3197 ng_btsocket_rfcomm_send_credits(ng_btsocket_rfcomm_pcb_p pcb)
3202 mtx_assert(&pcb->pcb_mtx, MA_OWNED);
3203 mtx_assert(&pcb->session->session_mtx, MA_OWNED);
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);
3211 credits = sbspace(&pcb->so->so_rcv) / pcb->mtu;
3213 if (pcb->rx_cred + credits > RFCOMM_MAX_CREDITS)
3214 credits = RFCOMM_MAX_CREDITS - pcb->rx_cred;
3216 error = ng_btsocket_rfcomm_send_uih(
3218 RFCOMM_MKADDRESS(INITIATOR(pcb->session),
3219 pcb->dlci), 1, credits, NULL);
3221 pcb->rx_cred += credits;
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);
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);
3237 } /* ng_btsocket_rfcomm_send_credits */
3239 /*****************************************************************************
3240 *****************************************************************************
3242 *****************************************************************************
3243 *****************************************************************************/
3246 * Send data from socket send buffer
3247 * Caller must hold pcb->pcb_mtx and pcb->session->session_mtx
3251 ng_btsocket_rfcomm_pcb_send(ng_btsocket_rfcomm_pcb_p pcb, int limit)
3253 struct mbuf *m = NULL;
3254 int sent, length, error;
3256 mtx_assert(&pcb->session->session_mtx, MA_OWNED);
3257 mtx_assert(&pcb->pcb_mtx, MA_OWNED);
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 ??? */
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,
3276 for (error = 0, sent = 0; sent < limit; sent ++) {
3277 length = min(pcb->mtu, pcb->so->so_snd.sb_cc);
3281 /* Get the chunk from the socket's send buffer */
3282 m = ng_btsocket_rfcomm_prepare_packet(&pcb->so->so_snd, length);
3288 sbdrop(&pcb->so->so_snd, length);
3290 error = ng_btsocket_rfcomm_send_uih(pcb->session,
3291 RFCOMM_MKADDRESS(INITIATOR(pcb->session),
3292 pcb->dlci), 0, 0, m);
3297 if (pcb->flags & NG_BTSOCKET_RFCOMM_DLC_CFC)
3298 pcb->tx_cred -= sent;
3300 if (error == 0 && sent > 0) {
3301 pcb->flags &= ~NG_BTSOCKET_RFCOMM_DLC_SENDING;
3306 } /* ng_btsocket_rfcomm_pcb_send */
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
3315 ng_btsocket_rfcomm_pcb_kill(ng_btsocket_rfcomm_pcb_p pcb, int error)
3317 ng_btsocket_rfcomm_session_p s = pcb->session;
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);
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);
3327 mtx_assert(&pcb->session->session_mtx, MA_OWNED);
3328 mtx_assert(&pcb->pcb_mtx, MA_OWNED);
3330 if (pcb->flags & NG_BTSOCKET_RFCOMM_DLC_TIMO)
3331 ng_btsocket_rfcomm_untimeout(pcb);
3333 /* Detach DLC from the session. Does not matter which state DLC in */
3334 LIST_REMOVE(pcb, session_next);
3335 pcb->session = NULL;
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);
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);
3350 case NG_BTSOCKET_RFCOMM_SESSION_CLOSED:
3351 case NG_BTSOCKET_RFCOMM_SESSION_DISCONNECTING:
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
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);
3364 s->state = NG_BTSOCKET_RFCOMM_SESSION_DISCONNECTING;
3369 case NG_BTSOCKET_RFCOMM_SESSION_CONNECTING:
3370 case NG_BTSOCKET_RFCOMM_SESSION_CONNECTED:
3371 s->state = NG_BTSOCKET_RFCOMM_SESSION_CLOSED;
3374 /* case NG_BTSOCKET_RFCOMM_SESSION_LISTENING: */
3376 panic("%s: Invalid session state=%d, flags=%#x\n",
3377 __func__, s->state, s->flags);
3381 ng_btsocket_rfcomm_task_wakeup();
3383 } /* ng_btsocket_rfcomm_pcb_kill */
3386 * Look for given dlci for given RFCOMM session. Caller must hold s->session_mtx
3389 static ng_btsocket_rfcomm_pcb_p
3390 ng_btsocket_rfcomm_pcb_by_dlci(ng_btsocket_rfcomm_session_p s, int dlci)
3392 ng_btsocket_rfcomm_pcb_p pcb = NULL;
3394 mtx_assert(&s->session_mtx, MA_OWNED);
3396 LIST_FOREACH(pcb, &s->dlcs, session_next)
3397 if (pcb->dlci == dlci)
3401 } /* ng_btsocket_rfcomm_pcb_by_dlci */
3404 * Look for socket that listens on given src address and given channel
3407 static ng_btsocket_rfcomm_pcb_p
3408 ng_btsocket_rfcomm_pcb_listener(bdaddr_p src, int channel)
3410 ng_btsocket_rfcomm_pcb_p pcb = NULL, pcb1 = NULL;
3412 mtx_lock(&ng_btsocket_rfcomm_sockets_mtx);
3414 LIST_FOREACH(pcb, &ng_btsocket_rfcomm_sockets, next) {
3415 if (pcb->channel != channel ||
3416 !(pcb->so->so_options & SO_ACCEPTCONN))
3419 if (bcmp(&pcb->src, src, sizeof(*src)) == 0)
3422 if (bcmp(&pcb->src, NG_HCI_BDADDR_ANY, sizeof(bdaddr_t)) == 0)
3426 mtx_unlock(&ng_btsocket_rfcomm_sockets_mtx);
3428 return ((pcb != NULL)? pcb : pcb1);
3429 } /* ng_btsocket_rfcomm_pcb_listener */
3431 /*****************************************************************************
3432 *****************************************************************************
3434 *****************************************************************************
3435 *****************************************************************************/
3438 * Set timeout. Caller MUST hold pcb_mtx
3442 ng_btsocket_rfcomm_timeout(ng_btsocket_rfcomm_pcb_p pcb)
3444 mtx_assert(&pcb->pcb_mtx, MA_OWNED);
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);
3452 panic("%s: Duplicated socket timeout?!\n", __func__);
3453 } /* ng_btsocket_rfcomm_timeout */
3456 * Unset pcb timeout. Caller MUST hold pcb_mtx
3460 ng_btsocket_rfcomm_untimeout(ng_btsocket_rfcomm_pcb_p pcb)
3462 mtx_assert(&pcb->pcb_mtx, MA_OWNED);
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;
3469 panic("%s: No socket timeout?!\n", __func__);
3470 } /* ng_btsocket_rfcomm_timeout */
3473 * Process pcb timeout
3477 ng_btsocket_rfcomm_process_timeout(void *xpcb)
3479 ng_btsocket_rfcomm_pcb_p pcb = (ng_btsocket_rfcomm_pcb_p) xpcb;
3481 mtx_lock(&pcb->pcb_mtx);
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);
3487 pcb->flags &= ~NG_BTSOCKET_RFCOMM_DLC_TIMO;
3488 pcb->flags |= NG_BTSOCKET_RFCOMM_DLC_TIMEDOUT;
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;
3496 case NG_BTSOCKET_RFCOMM_DLC_W4_CONNECT:
3497 case NG_BTSOCKET_RFCOMM_DLC_DISCONNECTING:
3502 "%s: DLC timeout in invalid state, dlci=%d, state=%d, flags=%#x\n",
3503 __func__, pcb->dlci, pcb->state, pcb->flags);
3507 ng_btsocket_rfcomm_task_wakeup();
3509 mtx_unlock(&pcb->pcb_mtx);
3510 } /* ng_btsocket_rfcomm_process_timeout */
3513 * Get up to length bytes from the socket buffer
3516 static struct mbuf *
3517 ng_btsocket_rfcomm_prepare_packet(struct sockbuf *sb, int length)
3519 struct mbuf *top = NULL, *m = NULL, *n = NULL, *nextpkt = NULL;
3520 int mlen, noff, len;
3522 MGETHDR(top, MB_DONTWAIT, MT_DATA);
3526 top->m_pkthdr.len = length;
3532 nextpkt = n->m_nextpkt;
3535 while (length > 0 && n != NULL) {
3536 len = min(mlen - m->m_len, n->m_len - noff);
3540 bcopy(mtod(n, caddr_t)+noff, mtod(m, caddr_t)+m->m_len, len);
3545 if (length > 0 && m->m_len == mlen) {
3546 MGET(m->m_next, MB_DONTWAIT, MT_DATA);
3547 if (m->m_next == NULL) {
3557 if (noff == n->m_len) {
3564 nextpkt = (n != NULL)? n->m_nextpkt : NULL;
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);
3574 } /* ng_btsocket_rfcomm_prepare_packet */