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/ioccom.h>
43 #include <sys/kernel.h>
45 #include <sys/malloc.h>
47 #include <sys/mutex.h>
49 #include <sys/protosw.h>
50 #include <sys/queue.h>
51 #include <sys/socket.h>
52 #include <sys/socketvar.h>
53 #include <sys/sysctl.h>
54 #include <sys/taskqueue.h>
56 #include "ng_message.h"
58 #include "bluetooth/include/ng_bluetooth.h"
59 #include "bluetooth/include/ng_hci.h"
60 #include "bluetooth/include/ng_l2cap.h"
61 #include "bluetooth/include/ng_btsocket.h"
62 #include "bluetooth/include/ng_btsocket_l2cap.h"
63 #include "bluetooth/include/ng_btsocket_rfcomm.h"
66 #ifdef NG_SEPARATE_MALLOC
67 MALLOC_DEFINE(M_NETGRAPH_BTSOCKET_RFCOMM, "netgraph_btsocks_rfcomm",
68 "Netgraph Bluetooth RFCOMM sockets");
70 #define M_NETGRAPH_BTSOCKET_RFCOMM M_NETGRAPH
71 #endif /* NG_SEPARATE_MALLOC */
74 #define NG_BTSOCKET_RFCOMM_INFO \
75 if (ng_btsocket_rfcomm_debug_level >= NG_BTSOCKET_INFO_LEVEL) \
78 #define NG_BTSOCKET_RFCOMM_WARN \
79 if (ng_btsocket_rfcomm_debug_level >= NG_BTSOCKET_WARN_LEVEL) \
82 #define NG_BTSOCKET_RFCOMM_ERR \
83 if (ng_btsocket_rfcomm_debug_level >= NG_BTSOCKET_ERR_LEVEL) \
86 #define NG_BTSOCKET_RFCOMM_ALERT \
87 if (ng_btsocket_rfcomm_debug_level >= NG_BTSOCKET_ALERT_LEVEL) \
92 /* Local prototypes */
93 static void ng_btsocket_rfcomm_upcall
94 (struct socket *so, void *arg, int waitflag);
95 static void ng_btsocket_rfcomm_sessions_task
96 (void *ctx, int pending);
97 static void ng_btsocket_rfcomm_session_task
98 (ng_btsocket_rfcomm_session_p s);
99 #define ng_btsocket_rfcomm_task_wakeup() \
100 taskqueue_enqueue(taskqueue_swi_giant, &ng_btsocket_rfcomm_task)
102 static ng_btsocket_rfcomm_pcb_p ng_btsocket_rfcomm_connect_ind
103 (ng_btsocket_rfcomm_session_p s, int channel);
104 static void ng_btsocket_rfcomm_connect_cfm
105 (ng_btsocket_rfcomm_session_p s);
107 static int ng_btsocket_rfcomm_session_create
108 (ng_btsocket_rfcomm_session_p *sp, struct socket *l2so,
109 bdaddr_p src, bdaddr_p dst, struct thread *td);
110 static int ng_btsocket_rfcomm_session_accept
111 (ng_btsocket_rfcomm_session_p s0);
112 static int ng_btsocket_rfcomm_session_connect
113 (ng_btsocket_rfcomm_session_p s);
114 static int ng_btsocket_rfcomm_session_receive
115 (ng_btsocket_rfcomm_session_p s);
116 static int ng_btsocket_rfcomm_session_send
117 (ng_btsocket_rfcomm_session_p s);
118 static void ng_btsocket_rfcomm_session_clean
119 (ng_btsocket_rfcomm_session_p s);
120 static void ng_btsocket_rfcomm_session_process_pcb
121 (ng_btsocket_rfcomm_session_p s);
122 static ng_btsocket_rfcomm_session_p ng_btsocket_rfcomm_session_by_addr
123 (bdaddr_p src, bdaddr_p dst);
125 static int ng_btsocket_rfcomm_receive_frame
126 (ng_btsocket_rfcomm_session_p s, struct mbuf *m0);
127 static int ng_btsocket_rfcomm_receive_sabm
128 (ng_btsocket_rfcomm_session_p s, int dlci);
129 static int ng_btsocket_rfcomm_receive_disc
130 (ng_btsocket_rfcomm_session_p s, int dlci);
131 static int ng_btsocket_rfcomm_receive_ua
132 (ng_btsocket_rfcomm_session_p s, int dlci);
133 static int ng_btsocket_rfcomm_receive_dm
134 (ng_btsocket_rfcomm_session_p s, int dlci);
135 static int ng_btsocket_rfcomm_receive_uih
136 (ng_btsocket_rfcomm_session_p s, int dlci, int pf, struct mbuf *m0);
137 static int ng_btsocket_rfcomm_receive_mcc
138 (ng_btsocket_rfcomm_session_p s, struct mbuf *m0);
139 static int ng_btsocket_rfcomm_receive_test
140 (ng_btsocket_rfcomm_session_p s, struct mbuf *m0);
141 static int ng_btsocket_rfcomm_receive_fc
142 (ng_btsocket_rfcomm_session_p s, struct mbuf *m0);
143 static int ng_btsocket_rfcomm_receive_msc
144 (ng_btsocket_rfcomm_session_p s, struct mbuf *m0);
145 static int ng_btsocket_rfcomm_receive_rpn
146 (ng_btsocket_rfcomm_session_p s, struct mbuf *m0);
147 static int ng_btsocket_rfcomm_receive_rls
148 (ng_btsocket_rfcomm_session_p s, struct mbuf *m0);
149 static int ng_btsocket_rfcomm_receive_pn
150 (ng_btsocket_rfcomm_session_p s, struct mbuf *m0);
151 static void ng_btsocket_rfcomm_set_pn
152 (ng_btsocket_rfcomm_pcb_p pcb, u_int8_t cr, u_int8_t flow_control,
153 u_int8_t credits, u_int16_t mtu);
155 static int ng_btsocket_rfcomm_send_command
156 (ng_btsocket_rfcomm_session_p s, u_int8_t type, u_int8_t dlci);
157 static int ng_btsocket_rfcomm_send_uih
158 (ng_btsocket_rfcomm_session_p s, u_int8_t address, u_int8_t pf,
159 u_int8_t credits, struct mbuf *data);
160 static int ng_btsocket_rfcomm_send_msc
161 (ng_btsocket_rfcomm_pcb_p pcb);
162 static int ng_btsocket_rfcomm_send_pn
163 (ng_btsocket_rfcomm_pcb_p pcb);
164 static int ng_btsocket_rfcomm_send_credits
165 (ng_btsocket_rfcomm_pcb_p pcb);
167 static int ng_btsocket_rfcomm_pcb_send
168 (ng_btsocket_rfcomm_pcb_p pcb, int limit);
169 static void ng_btsocket_rfcomm_pcb_kill
170 (ng_btsocket_rfcomm_pcb_p pcb, int error);
171 static ng_btsocket_rfcomm_pcb_p ng_btsocket_rfcomm_pcb_by_dlci
172 (ng_btsocket_rfcomm_session_p s, int dlci);
173 static ng_btsocket_rfcomm_pcb_p ng_btsocket_rfcomm_pcb_listener
174 (bdaddr_p src, int channel);
176 static void ng_btsocket_rfcomm_timeout
177 (ng_btsocket_rfcomm_pcb_p pcb);
178 static void ng_btsocket_rfcomm_untimeout
179 (ng_btsocket_rfcomm_pcb_p pcb);
180 static void ng_btsocket_rfcomm_process_timeout
183 static struct mbuf * ng_btsocket_rfcomm_prepare_packet
184 (struct sockbuf *sb, int length);
187 extern int ifqmaxlen;
188 static u_int32_t ng_btsocket_rfcomm_debug_level;
189 static u_int32_t ng_btsocket_rfcomm_timo;
190 struct task ng_btsocket_rfcomm_task;
191 static LIST_HEAD(, ng_btsocket_rfcomm_session) ng_btsocket_rfcomm_sessions;
192 static struct mtx ng_btsocket_rfcomm_sessions_mtx;
193 static LIST_HEAD(, ng_btsocket_rfcomm_pcb) ng_btsocket_rfcomm_sockets;
194 static struct mtx ng_btsocket_rfcomm_sockets_mtx;
197 SYSCTL_DECL(_net_bluetooth_rfcomm_sockets);
198 SYSCTL_NODE(_net_bluetooth_rfcomm_sockets, OID_AUTO, stream, CTLFLAG_RW,
199 0, "Bluetooth STREAM RFCOMM sockets family");
200 SYSCTL_INT(_net_bluetooth_rfcomm_sockets_stream, OID_AUTO, debug_level,
202 &ng_btsocket_rfcomm_debug_level, NG_BTSOCKET_INFO_LEVEL,
203 "Bluetooth STREAM RFCOMM sockets debug level");
204 SYSCTL_INT(_net_bluetooth_rfcomm_sockets_stream, OID_AUTO, timeout,
206 &ng_btsocket_rfcomm_timo, 60,
207 "Bluetooth STREAM RFCOMM sockets timeout");
209 /*****************************************************************************
210 *****************************************************************************
212 *****************************************************************************
213 *****************************************************************************/
215 static u_int8_t ng_btsocket_rfcomm_crc_table[256] = {
216 0x00, 0x91, 0xe3, 0x72, 0x07, 0x96, 0xe4, 0x75,
217 0x0e, 0x9f, 0xed, 0x7c, 0x09, 0x98, 0xea, 0x7b,
218 0x1c, 0x8d, 0xff, 0x6e, 0x1b, 0x8a, 0xf8, 0x69,
219 0x12, 0x83, 0xf1, 0x60, 0x15, 0x84, 0xf6, 0x67,
221 0x38, 0xa9, 0xdb, 0x4a, 0x3f, 0xae, 0xdc, 0x4d,
222 0x36, 0xa7, 0xd5, 0x44, 0x31, 0xa0, 0xd2, 0x43,
223 0x24, 0xb5, 0xc7, 0x56, 0x23, 0xb2, 0xc0, 0x51,
224 0x2a, 0xbb, 0xc9, 0x58, 0x2d, 0xbc, 0xce, 0x5f,
226 0x70, 0xe1, 0x93, 0x02, 0x77, 0xe6, 0x94, 0x05,
227 0x7e, 0xef, 0x9d, 0x0c, 0x79, 0xe8, 0x9a, 0x0b,
228 0x6c, 0xfd, 0x8f, 0x1e, 0x6b, 0xfa, 0x88, 0x19,
229 0x62, 0xf3, 0x81, 0x10, 0x65, 0xf4, 0x86, 0x17,
231 0x48, 0xd9, 0xab, 0x3a, 0x4f, 0xde, 0xac, 0x3d,
232 0x46, 0xd7, 0xa5, 0x34, 0x41, 0xd0, 0xa2, 0x33,
233 0x54, 0xc5, 0xb7, 0x26, 0x53, 0xc2, 0xb0, 0x21,
234 0x5a, 0xcb, 0xb9, 0x28, 0x5d, 0xcc, 0xbe, 0x2f,
236 0xe0, 0x71, 0x03, 0x92, 0xe7, 0x76, 0x04, 0x95,
237 0xee, 0x7f, 0x0d, 0x9c, 0xe9, 0x78, 0x0a, 0x9b,
238 0xfc, 0x6d, 0x1f, 0x8e, 0xfb, 0x6a, 0x18, 0x89,
239 0xf2, 0x63, 0x11, 0x80, 0xf5, 0x64, 0x16, 0x87,
241 0xd8, 0x49, 0x3b, 0xaa, 0xdf, 0x4e, 0x3c, 0xad,
242 0xd6, 0x47, 0x35, 0xa4, 0xd1, 0x40, 0x32, 0xa3,
243 0xc4, 0x55, 0x27, 0xb6, 0xc3, 0x52, 0x20, 0xb1,
244 0xca, 0x5b, 0x29, 0xb8, 0xcd, 0x5c, 0x2e, 0xbf,
246 0x90, 0x01, 0x73, 0xe2, 0x97, 0x06, 0x74, 0xe5,
247 0x9e, 0x0f, 0x7d, 0xec, 0x99, 0x08, 0x7a, 0xeb,
248 0x8c, 0x1d, 0x6f, 0xfe, 0x8b, 0x1a, 0x68, 0xf9,
249 0x82, 0x13, 0x61, 0xf0, 0x85, 0x14, 0x66, 0xf7,
251 0xa8, 0x39, 0x4b, 0xda, 0xaf, 0x3e, 0x4c, 0xdd,
252 0xa6, 0x37, 0x45, 0xd4, 0xa1, 0x30, 0x42, 0xd3,
253 0xb4, 0x25, 0x57, 0xc6, 0xb3, 0x22, 0x50, 0xc1,
254 0xba, 0x2b, 0x59, 0xc8, 0xbd, 0x2c, 0x5e, 0xcf
259 ng_btsocket_rfcomm_crc(u_int8_t *data, int length)
264 crc = ng_btsocket_rfcomm_crc_table[crc ^ *data++];
267 } /* ng_btsocket_rfcomm_crc */
271 ng_btsocket_rfcomm_fcs2(u_int8_t *data)
273 return (0xff - ng_btsocket_rfcomm_crc(data, 2));
274 } /* ng_btsocket_rfcomm_fcs2 */
278 ng_btsocket_rfcomm_fcs3(u_int8_t *data)
280 return (0xff - ng_btsocket_rfcomm_crc(data, 3));
281 } /* ng_btsocket_rfcomm_fcs3 */
286 * From Bluetooth spec
288 * "... In 07.10, the frame check sequence (FCS) is calculated on different
289 * sets of fields for different frame types. These are the fields that the
290 * FCS are calculated on:
292 * For SABM, DISC, UA, DM frames: on Address, Control and length field.
293 * For UIH frames: on Address and Control field.
295 * (This is stated here for clarification, and to set the standard for RFCOMM;
296 * the fields included in FCS calculation have actually changed in version
297 * 7.0.0 of TS 07.10, but RFCOMM will not change the FCS calculation scheme
298 * from the one above.) ..."
302 ng_btsocket_rfcomm_check_fcs(u_int8_t *data, int type, u_int8_t fcs)
304 if (type != RFCOMM_FRAME_UIH)
305 return (ng_btsocket_rfcomm_fcs3(data) != fcs);
307 return (ng_btsocket_rfcomm_fcs2(data) != fcs);
308 } /* ng_btsocket_rfcomm_check_fcs */
310 /*****************************************************************************
311 *****************************************************************************
313 *****************************************************************************
314 *****************************************************************************/
317 * Initialize everything
321 ng_btsocket_rfcomm_init(void)
323 ng_btsocket_rfcomm_debug_level = NG_BTSOCKET_WARN_LEVEL;
324 ng_btsocket_rfcomm_timo = 60;
327 TASK_INIT(&ng_btsocket_rfcomm_task, 0,
328 ng_btsocket_rfcomm_sessions_task, NULL);
330 /* RFCOMM sessions list */
331 LIST_INIT(&ng_btsocket_rfcomm_sessions);
332 mtx_init(&ng_btsocket_rfcomm_sessions_mtx,
333 "btsocks_rfcomm_sessions_mtx", NULL, MTX_DEF);
335 /* RFCOMM sockets list */
336 LIST_INIT(&ng_btsocket_rfcomm_sockets);
337 mtx_init(&ng_btsocket_rfcomm_sockets_mtx,
338 "btsocks_rfcomm_sockets_mtx", NULL, MTX_DEF);
339 } /* ng_btsocket_rfcomm_init */
342 * Abort connection on socket
346 ng_btsocket_rfcomm_abort(struct socket *so)
349 so->so_error = ECONNABORTED;
350 (void)ng_btsocket_rfcomm_disconnect(so);
351 } /* ng_btsocket_rfcomm_abort */
354 ng_btsocket_rfcomm_close(struct socket *so)
357 (void)ng_btsocket_rfcomm_disconnect(so);
358 } /* ng_btsocket_rfcomm_close */
361 * Accept connection on socket. Nothing to do here, socket must be connected
362 * and ready, so just return peer address and be done with it.
366 ng_btsocket_rfcomm_accept(struct socket *so, struct sockaddr **nam)
368 return (ng_btsocket_rfcomm_peeraddr(so, nam));
369 } /* ng_btsocket_rfcomm_accept */
372 * Create and attach new socket
376 ng_btsocket_rfcomm_attach(struct socket *so, int proto, struct thread *td)
378 ng_btsocket_rfcomm_pcb_p pcb = so2rfcomm_pcb(so);
381 /* Check socket and protocol */
382 if (so->so_type != SOCK_STREAM)
383 return (ESOCKTNOSUPPORT);
385 #if 0 /* XXX sonewconn() calls "pru_attach" with proto == 0 */
387 if (proto != BLUETOOTH_PROTO_RFCOMM)
388 return (EPROTONOSUPPORT);
394 /* Reserve send and receive space if it is not reserved yet */
395 if ((so->so_snd.sb_hiwat == 0) || (so->so_rcv.sb_hiwat == 0)) {
396 error = soreserve(so, NG_BTSOCKET_RFCOMM_SENDSPACE,
397 NG_BTSOCKET_RFCOMM_RECVSPACE);
402 /* Allocate the PCB */
403 MALLOC(pcb, ng_btsocket_rfcomm_pcb_p, sizeof(*pcb),
404 M_NETGRAPH_BTSOCKET_RFCOMM, M_WAITOK | M_NULLOK | M_ZERO);
408 /* Link the PCB and the socket */
409 so->so_pcb = (caddr_t) pcb;
413 pcb->state = NG_BTSOCKET_RFCOMM_DLC_CLOSED;
414 pcb->flags = NG_BTSOCKET_RFCOMM_DLC_CFC;
417 pcb->rmodem = (RFCOMM_MODEM_RTC | RFCOMM_MODEM_RTR | RFCOMM_MODEM_DV);
419 pcb->mtu = RFCOMM_DEFAULT_MTU;
421 pcb->rx_cred = RFCOMM_DEFAULT_CREDITS;
423 mtx_init(&pcb->pcb_mtx, "btsocks_rfcomm_pcb_mtx", NULL, MTX_DEF);
424 callout_handle_init(&pcb->timo);
426 /* Add the PCB to the list */
427 mtx_lock(&ng_btsocket_rfcomm_sockets_mtx);
428 LIST_INSERT_HEAD(&ng_btsocket_rfcomm_sockets, pcb, next);
429 mtx_unlock(&ng_btsocket_rfcomm_sockets_mtx);
432 } /* ng_btsocket_rfcomm_attach */
439 ng_btsocket_rfcomm_bind(struct socket *so, struct sockaddr *nam,
442 ng_btsocket_rfcomm_pcb_t *pcb = so2rfcomm_pcb(so), *pcb1;
443 struct sockaddr_rfcomm *sa = (struct sockaddr_rfcomm *) nam;
451 if (sa->rfcomm_family != AF_BLUETOOTH)
452 return (EAFNOSUPPORT);
453 if (sa->rfcomm_len != sizeof(*sa))
455 if (sa->rfcomm_channel > 30)
458 mtx_lock(&pcb->pcb_mtx);
460 if (sa->rfcomm_channel != 0) {
461 mtx_lock(&ng_btsocket_rfcomm_sockets_mtx);
463 LIST_FOREACH(pcb1, &ng_btsocket_rfcomm_sockets, next) {
464 if (pcb1->channel == sa->rfcomm_channel &&
465 bcmp(&pcb1->src, &sa->rfcomm_bdaddr,
466 sizeof(pcb1->src)) == 0) {
467 mtx_unlock(&ng_btsocket_rfcomm_sockets_mtx);
468 mtx_unlock(&pcb->pcb_mtx);
474 mtx_unlock(&ng_btsocket_rfcomm_sockets_mtx);
477 bcopy(&sa->rfcomm_bdaddr, &pcb->src, sizeof(pcb->src));
478 pcb->channel = sa->rfcomm_channel;
480 mtx_unlock(&pcb->pcb_mtx);
483 } /* ng_btsocket_rfcomm_bind */
490 ng_btsocket_rfcomm_connect(struct socket *so, struct sockaddr *nam,
493 ng_btsocket_rfcomm_pcb_t *pcb = so2rfcomm_pcb(so);
494 struct sockaddr_rfcomm *sa = (struct sockaddr_rfcomm *) nam;
495 ng_btsocket_rfcomm_session_t *s = NULL;
496 struct socket *l2so = NULL;
505 if (sa->rfcomm_family != AF_BLUETOOTH)
506 return (EAFNOSUPPORT);
507 if (sa->rfcomm_len != sizeof(*sa))
509 if (sa->rfcomm_channel > 30)
511 if (sa->rfcomm_channel == 0 ||
512 bcmp(&sa->rfcomm_bdaddr, NG_HCI_BDADDR_ANY, sizeof(bdaddr_t)) == 0)
513 return (EDESTADDRREQ);
516 * XXX FIXME - This is FUBAR. socreate() will call soalloc(1), i.e.
517 * soalloc() is allowed to sleep in MALLOC. This creates "could sleep"
518 * WITNESS warnings. To work around this problem we will create L2CAP
519 * socket first and then check if we actually need it. Note that we
520 * will not check for errors in socreate() because if we failed to
521 * create L2CAP socket at this point we still might have already open
525 error = socreate(PF_BLUETOOTH, &l2so, SOCK_SEQPACKET,
526 BLUETOOTH_PROTO_L2CAP, td->td_ucred, td);
529 * Look for session between "pcb->src" and "sa->rfcomm_bdaddr" (dst)
532 mtx_lock(&ng_btsocket_rfcomm_sessions_mtx);
534 s = ng_btsocket_rfcomm_session_by_addr(&pcb->src, &sa->rfcomm_bdaddr);
537 * We need to create new RFCOMM session. Check if we have L2CAP
538 * socket. If l2so == NULL then error has the error code from
543 mtx_unlock(&ng_btsocket_rfcomm_sessions_mtx);
547 error = ng_btsocket_rfcomm_session_create(&s, l2so,
548 &pcb->src, &sa->rfcomm_bdaddr, td);
550 mtx_unlock(&ng_btsocket_rfcomm_sessions_mtx);
555 } else if (l2so != NULL)
556 soclose(l2so); /* we don't need new L2CAP socket */
559 * Check if we already have the same DLCI the the same session
562 mtx_lock(&s->session_mtx);
563 mtx_lock(&pcb->pcb_mtx);
565 dlci = RFCOMM_MKDLCI(!INITIATOR(s), sa->rfcomm_channel);
567 if (ng_btsocket_rfcomm_pcb_by_dlci(s, dlci) != NULL) {
568 mtx_unlock(&pcb->pcb_mtx);
569 mtx_unlock(&s->session_mtx);
570 mtx_unlock(&ng_btsocket_rfcomm_sessions_mtx);
576 * Check session state and if its not acceptable then refuse connection
580 case NG_BTSOCKET_RFCOMM_SESSION_CONNECTING:
581 case NG_BTSOCKET_RFCOMM_SESSION_CONNECTED:
582 case NG_BTSOCKET_RFCOMM_SESSION_OPEN:
584 * Update destination address and channel and attach
588 bcopy(&sa->rfcomm_bdaddr, &pcb->dst, sizeof(pcb->dst));
589 pcb->channel = sa->rfcomm_channel;
592 LIST_INSERT_HEAD(&s->dlcs, pcb, session_next);
595 ng_btsocket_rfcomm_timeout(pcb);
596 soisconnecting(pcb->so);
598 if (s->state == NG_BTSOCKET_RFCOMM_SESSION_OPEN) {
600 bcopy(&so2l2cap_pcb(s->l2so)->src, &pcb->src,
603 pcb->state = NG_BTSOCKET_RFCOMM_DLC_CONFIGURING;
605 error = ng_btsocket_rfcomm_send_pn(pcb);
607 error = ng_btsocket_rfcomm_task_wakeup();
609 pcb->state = NG_BTSOCKET_RFCOMM_DLC_W4_CONNECT;
617 mtx_unlock(&pcb->pcb_mtx);
618 mtx_unlock(&s->session_mtx);
619 mtx_unlock(&ng_btsocket_rfcomm_sessions_mtx);
622 } /* ng_btsocket_rfcomm_connect */
625 * Process ioctl's calls on socket.
626 * XXX FIXME this should provide interface to the RFCOMM multiplexor channel
630 ng_btsocket_rfcomm_control(struct socket *so, u_long cmd, caddr_t data,
631 struct ifnet *ifp, struct thread *td)
634 } /* ng_btsocket_rfcomm_control */
637 * Process getsockopt/setsockopt system calls
641 ng_btsocket_rfcomm_ctloutput(struct socket *so, struct sockopt *sopt)
643 ng_btsocket_rfcomm_pcb_p pcb = so2rfcomm_pcb(so);
644 struct ng_btsocket_rfcomm_fc_info fcinfo;
649 if (sopt->sopt_level != SOL_RFCOMM)
652 mtx_lock(&pcb->pcb_mtx);
654 switch (sopt->sopt_dir) {
656 switch (sopt->sopt_name) {
658 error = sooptcopyout(sopt, &pcb->mtu, sizeof(pcb->mtu));
661 case SO_RFCOMM_FC_INFO:
662 fcinfo.lmodem = pcb->lmodem;
663 fcinfo.rmodem = pcb->rmodem;
664 fcinfo.tx_cred = pcb->tx_cred;
665 fcinfo.rx_cred = pcb->rx_cred;
666 fcinfo.cfc = (pcb->flags & NG_BTSOCKET_RFCOMM_DLC_CFC)?
670 error = sooptcopyout(sopt, &fcinfo, sizeof(fcinfo));
680 switch (sopt->sopt_name) {
692 mtx_unlock(&pcb->pcb_mtx);
695 } /* ng_btsocket_rfcomm_ctloutput */
698 * Detach and destroy socket
702 ng_btsocket_rfcomm_detach(struct socket *so)
704 ng_btsocket_rfcomm_pcb_p pcb = so2rfcomm_pcb(so);
706 KASSERT(pcb != NULL, ("ng_btsocket_rfcomm_detach: pcb == NULL"));
708 mtx_lock(&pcb->pcb_mtx);
710 switch (pcb->state) {
711 case NG_BTSOCKET_RFCOMM_DLC_W4_CONNECT:
712 case NG_BTSOCKET_RFCOMM_DLC_CONFIGURING:
713 case NG_BTSOCKET_RFCOMM_DLC_CONNECTING:
714 case NG_BTSOCKET_RFCOMM_DLC_CONNECTED:
715 /* XXX What to do with pending request? */
716 if (pcb->flags & NG_BTSOCKET_RFCOMM_DLC_TIMO)
717 ng_btsocket_rfcomm_untimeout(pcb);
719 if (pcb->state == NG_BTSOCKET_RFCOMM_DLC_W4_CONNECT)
720 pcb->flags |= NG_BTSOCKET_RFCOMM_DLC_DETACHED;
722 pcb->state = NG_BTSOCKET_RFCOMM_DLC_DISCONNECTING;
724 ng_btsocket_rfcomm_task_wakeup();
727 case NG_BTSOCKET_RFCOMM_DLC_DISCONNECTING:
728 ng_btsocket_rfcomm_task_wakeup();
732 while (pcb->state != NG_BTSOCKET_RFCOMM_DLC_CLOSED)
733 msleep(&pcb->state, &pcb->pcb_mtx, PZERO, "rf_det", 0);
735 if (pcb->session != NULL)
736 panic("%s: pcb->session != NULL\n", __func__);
737 if (pcb->flags & NG_BTSOCKET_RFCOMM_DLC_TIMO)
738 panic("%s: timeout on closed DLC, flags=%#x\n",
739 __func__, pcb->flags);
741 mtx_lock(&ng_btsocket_rfcomm_sockets_mtx);
742 LIST_REMOVE(pcb, next);
743 mtx_unlock(&ng_btsocket_rfcomm_sockets_mtx);
745 mtx_unlock(&pcb->pcb_mtx);
747 mtx_destroy(&pcb->pcb_mtx);
748 bzero(pcb, sizeof(*pcb));
749 FREE(pcb, M_NETGRAPH_BTSOCKET_RFCOMM);
751 soisdisconnected(so);
753 } /* ng_btsocket_rfcomm_detach */
760 ng_btsocket_rfcomm_disconnect(struct socket *so)
762 ng_btsocket_rfcomm_pcb_p pcb = so2rfcomm_pcb(so);
767 mtx_lock(&pcb->pcb_mtx);
769 if (pcb->state == NG_BTSOCKET_RFCOMM_DLC_DISCONNECTING) {
770 mtx_unlock(&pcb->pcb_mtx);
771 return (EINPROGRESS);
774 /* XXX What to do with pending request? */
775 if (pcb->flags & NG_BTSOCKET_RFCOMM_DLC_TIMO)
776 ng_btsocket_rfcomm_untimeout(pcb);
778 switch (pcb->state) {
779 case NG_BTSOCKET_RFCOMM_DLC_CONFIGURING: /* XXX can we get here? */
780 case NG_BTSOCKET_RFCOMM_DLC_CONNECTING: /* XXX can we get here? */
781 case NG_BTSOCKET_RFCOMM_DLC_CONNECTED:
784 * Just change DLC state and enqueue RFCOMM task. It will
785 * queue and send DISC on the DLC.
788 pcb->state = NG_BTSOCKET_RFCOMM_DLC_DISCONNECTING;
789 soisdisconnecting(so);
791 ng_btsocket_rfcomm_task_wakeup();
794 case NG_BTSOCKET_RFCOMM_DLC_CLOSED:
795 case NG_BTSOCKET_RFCOMM_DLC_W4_CONNECT:
799 panic("%s: Invalid DLC state=%d, flags=%#x\n",
800 __func__, pcb->state, pcb->flags);
804 mtx_unlock(&pcb->pcb_mtx);
807 } /* ng_btsocket_rfcomm_disconnect */
810 * Listen on socket. First call to listen() will create listening RFCOMM session
814 ng_btsocket_rfcomm_listen(struct socket *so, int backlog, struct thread *td)
816 ng_btsocket_rfcomm_pcb_p pcb = so2rfcomm_pcb(so), pcb1;
817 ng_btsocket_rfcomm_session_p s = NULL;
818 struct socket *l2so = NULL;
819 int error, socreate_error, usedchannels;
823 if (pcb->channel > 30)
824 return (EADDRNOTAVAIL);
828 mtx_lock(&pcb->pcb_mtx);
830 if (pcb->channel == 0) {
831 mtx_lock(&ng_btsocket_rfcomm_sockets_mtx);
833 LIST_FOREACH(pcb1, &ng_btsocket_rfcomm_sockets, next)
834 if (pcb1->channel != 0 &&
835 bcmp(&pcb1->src, &pcb->src, sizeof(pcb->src)) == 0)
836 usedchannels |= (1 << (pcb1->channel - 1));
838 for (pcb->channel = 30; pcb->channel > 0; pcb->channel --)
839 if (!(usedchannels & (1 << (pcb->channel - 1))))
842 if (pcb->channel == 0) {
843 mtx_unlock(&ng_btsocket_rfcomm_sockets_mtx);
844 mtx_unlock(&pcb->pcb_mtx);
846 return (EADDRNOTAVAIL);
849 mtx_unlock(&ng_btsocket_rfcomm_sockets_mtx);
852 mtx_unlock(&pcb->pcb_mtx);
855 * XXX FIXME - This is FUBAR. socreate() will call soalloc(1), i.e.
856 * soalloc() is allowed to sleep in MALLOC. This creates "could sleep"
857 * WITNESS warnings. To work around this problem we will create L2CAP
858 * socket first and then check if we actually need it. Note that we
859 * will not check for errors in socreate() because if we failed to
860 * create L2CAP socket at this point we still might have already open
864 socreate_error = socreate(PF_BLUETOOTH, &l2so, SOCK_SEQPACKET,
865 BLUETOOTH_PROTO_L2CAP, td->td_ucred, td);
868 * Transition the socket and session into the LISTENING state. Check
869 * for collisions first, as there can only be one.
871 mtx_lock(&ng_btsocket_rfcomm_sessions_mtx);
873 error = solisten_proto_check(so);
878 LIST_FOREACH(s, &ng_btsocket_rfcomm_sessions, next)
879 if (s->state == NG_BTSOCKET_RFCOMM_SESSION_LISTENING)
884 * We need to create default RFCOMM session. Check if we have
885 * L2CAP socket. If l2so == NULL then error has the error code
889 error = socreate_error;
894 * Create default listen RFCOMM session. The default RFCOMM
895 * session will listen on ANY address.
897 * XXX FIXME Note that currently there is no way to adjust MTU
898 * for the default session.
900 error = ng_btsocket_rfcomm_session_create(&s, l2so,
901 NG_HCI_BDADDR_ANY, NULL, td);
907 solisten_proto(so, backlog);
910 mtx_unlock(&ng_btsocket_rfcomm_sessions_mtx);
912 * If we still have an l2so reference here, it's unneeded, so release
918 } /* ng_btsocket_listen */
925 ng_btsocket_rfcomm_peeraddr(struct socket *so, struct sockaddr **nam)
927 ng_btsocket_rfcomm_pcb_p pcb = so2rfcomm_pcb(so);
928 struct sockaddr_rfcomm sa;
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;
938 *nam = sodupsockaddr((struct sockaddr *) &sa, M_WAITOK | M_NULLOK);
940 return ((*nam == NULL)? ENOMEM : 0);
941 } /* ng_btsocket_rfcomm_peeraddr */
944 * Send data to socket
948 ng_btsocket_rfcomm_send(struct socket *so, int flags, struct mbuf *m,
949 struct sockaddr *nam, struct mbuf *control, struct thread *td)
951 ng_btsocket_rfcomm_pcb_t *pcb = so2rfcomm_pcb(so);
954 /* Check socket and input */
955 if (pcb == NULL || m == NULL || control != NULL) {
960 mtx_lock(&pcb->pcb_mtx);
962 /* Make sure DLC is connected */
963 if (pcb->state != NG_BTSOCKET_RFCOMM_DLC_CONNECTED) {
964 mtx_unlock(&pcb->pcb_mtx);
969 /* Put the packet on the socket's send queue and wakeup RFCOMM task */
970 sbappend(&pcb->so->so_snd, m);
973 if (!(pcb->flags & NG_BTSOCKET_RFCOMM_DLC_SENDING)) {
974 pcb->flags |= NG_BTSOCKET_RFCOMM_DLC_SENDING;
975 error = ng_btsocket_rfcomm_task_wakeup();
978 mtx_unlock(&pcb->pcb_mtx);
980 NG_FREE_M(m); /* checks for != NULL */
984 } /* ng_btsocket_rfcomm_send */
991 ng_btsocket_rfcomm_sockaddr(struct socket *so, struct sockaddr **nam)
993 ng_btsocket_rfcomm_pcb_p pcb = so2rfcomm_pcb(so);
994 struct sockaddr_rfcomm sa;
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;
1004 *nam = sodupsockaddr((struct sockaddr *) &sa, M_WAITOK | M_NULLOK);
1006 return ((*nam == NULL)? ENOMEM : 0);
1007 } /* ng_btsocket_rfcomm_sockaddr */
1010 * Upcall function for L2CAP sockets. Enqueue RFCOMM task.
1014 ng_btsocket_rfcomm_upcall(struct socket *so, void *arg, int waitflag)
1019 panic("%s: so == NULL\n", __func__);
1021 if ((error = ng_btsocket_rfcomm_task_wakeup()) != 0)
1022 NG_BTSOCKET_RFCOMM_ALERT(
1023 "%s: Could not enqueue RFCOMM task, error=%d\n", __func__, error);
1024 } /* ng_btsocket_rfcomm_upcall */
1027 * RFCOMM task. Will handle all RFCOMM sessions in one pass.
1028 * XXX FIXME does not scale very well
1032 ng_btsocket_rfcomm_sessions_task(void *ctx, int pending)
1034 ng_btsocket_rfcomm_session_p s = NULL, s_next = NULL;
1036 mtx_lock(&ng_btsocket_rfcomm_sessions_mtx);
1038 for (s = LIST_FIRST(&ng_btsocket_rfcomm_sessions); s != NULL; ) {
1039 mtx_lock(&s->session_mtx);
1040 s_next = LIST_NEXT(s, next);
1042 ng_btsocket_rfcomm_session_task(s);
1044 if (s->state == NG_BTSOCKET_RFCOMM_SESSION_CLOSED) {
1045 /* Unlink and clean the session */
1046 LIST_REMOVE(s, next);
1048 NG_BT_MBUFQ_DRAIN(&s->outq);
1049 if (!LIST_EMPTY(&s->dlcs))
1050 panic("%s: DLC list is not empty\n", __func__);
1052 /* Close L2CAP socket */
1053 s->l2so->so_upcallarg = NULL;
1054 s->l2so->so_upcall = NULL;
1055 SOCKBUF_LOCK(&s->l2so->so_rcv);
1056 s->l2so->so_rcv.sb_flags &= ~SB_UPCALL;
1057 SOCKBUF_UNLOCK(&s->l2so->so_rcv);
1058 SOCKBUF_LOCK(&s->l2so->so_snd);
1059 s->l2so->so_snd.sb_flags &= ~SB_UPCALL;
1060 SOCKBUF_UNLOCK(&s->l2so->so_snd);
1063 mtx_unlock(&s->session_mtx);
1065 mtx_destroy(&s->session_mtx);
1066 bzero(s, sizeof(*s));
1067 FREE(s, M_NETGRAPH_BTSOCKET_RFCOMM);
1069 mtx_unlock(&s->session_mtx);
1074 mtx_unlock(&ng_btsocket_rfcomm_sessions_mtx);
1075 } /* ng_btsocket_rfcomm_sessions_task */
1078 * Process RFCOMM session. Will handle all RFCOMM sockets in one pass.
1082 ng_btsocket_rfcomm_session_task(ng_btsocket_rfcomm_session_p s)
1084 mtx_assert(&s->session_mtx, MA_OWNED);
1086 if (s->l2so->so_rcv.sb_state & SBS_CANTRCVMORE) {
1087 NG_BTSOCKET_RFCOMM_INFO(
1088 "%s: L2CAP connection has been terminated, so=%p, so_state=%#x, so_count=%d, " \
1089 "state=%d, flags=%#x\n", __func__, s->l2so, s->l2so->so_state,
1090 s->l2so->so_count, s->state, s->flags);
1092 s->state = NG_BTSOCKET_RFCOMM_SESSION_CLOSED;
1093 ng_btsocket_rfcomm_session_clean(s);
1096 /* Now process upcall */
1098 /* Try to accept new L2CAP connection(s) */
1099 case NG_BTSOCKET_RFCOMM_SESSION_LISTENING:
1100 while (ng_btsocket_rfcomm_session_accept(s) == 0)
1104 /* Process the results of the L2CAP connect */
1105 case NG_BTSOCKET_RFCOMM_SESSION_CONNECTING:
1106 ng_btsocket_rfcomm_session_process_pcb(s);
1108 if (ng_btsocket_rfcomm_session_connect(s) != 0) {
1109 s->state = NG_BTSOCKET_RFCOMM_SESSION_CLOSED;
1110 ng_btsocket_rfcomm_session_clean(s);
1114 /* Try to receive/send more data */
1115 case NG_BTSOCKET_RFCOMM_SESSION_CONNECTED:
1116 case NG_BTSOCKET_RFCOMM_SESSION_OPEN:
1117 case NG_BTSOCKET_RFCOMM_SESSION_DISCONNECTING:
1118 ng_btsocket_rfcomm_session_process_pcb(s);
1120 if (ng_btsocket_rfcomm_session_receive(s) != 0) {
1121 s->state = NG_BTSOCKET_RFCOMM_SESSION_CLOSED;
1122 ng_btsocket_rfcomm_session_clean(s);
1123 } else if (ng_btsocket_rfcomm_session_send(s) != 0) {
1124 s->state = NG_BTSOCKET_RFCOMM_SESSION_CLOSED;
1125 ng_btsocket_rfcomm_session_clean(s);
1129 case NG_BTSOCKET_RFCOMM_SESSION_CLOSED:
1133 panic("%s: Invalid session state=%d, flags=%#x\n",
1134 __func__, s->state, s->flags);
1137 } /* ng_btsocket_rfcomm_session_task */
1140 * Process RFCOMM connection indicator. Caller must hold s->session_mtx
1143 static ng_btsocket_rfcomm_pcb_p
1144 ng_btsocket_rfcomm_connect_ind(ng_btsocket_rfcomm_session_p s, int channel)
1146 ng_btsocket_rfcomm_pcb_p pcb = NULL, pcb1 = NULL;
1147 ng_btsocket_l2cap_pcb_p l2pcb = NULL;
1148 struct socket *so1 = NULL;
1150 mtx_assert(&s->session_mtx, MA_OWNED);
1153 * Try to find RFCOMM socket that listens on given source address
1154 * and channel. This will return the best possible match.
1157 l2pcb = so2l2cap_pcb(s->l2so);
1158 pcb = ng_btsocket_rfcomm_pcb_listener(&l2pcb->src, channel);
1163 * Check the pending connections queue and if we have space then
1164 * create new socket and set proper source and destination address,
1168 mtx_lock(&pcb->pcb_mtx);
1170 if (pcb->so->so_qlen <= pcb->so->so_qlimit)
1171 so1 = sonewconn(pcb->so, 0);
1173 mtx_unlock(&pcb->pcb_mtx);
1179 * If we got here than we have created new socket. So complete the
1180 * connection. Set source and destination address from the session.
1183 pcb1 = so2rfcomm_pcb(so1);
1185 panic("%s: pcb1 == NULL\n", __func__);
1187 mtx_lock(&pcb1->pcb_mtx);
1189 bcopy(&l2pcb->src, &pcb1->src, sizeof(pcb1->src));
1190 bcopy(&l2pcb->dst, &pcb1->dst, sizeof(pcb1->dst));
1191 pcb1->channel = channel;
1193 /* Link new DLC to the session. We already hold s->session_mtx */
1194 LIST_INSERT_HEAD(&s->dlcs, pcb1, session_next);
1197 mtx_unlock(&pcb1->pcb_mtx);
1200 } /* ng_btsocket_rfcomm_connect_ind */
1203 * Process RFCOMM connect confirmation. Caller must hold s->session_mtx.
1207 ng_btsocket_rfcomm_connect_cfm(ng_btsocket_rfcomm_session_p s)
1209 ng_btsocket_rfcomm_pcb_p pcb = NULL, pcb_next = NULL;
1212 mtx_assert(&s->session_mtx, MA_OWNED);
1215 * Wake up all waiting sockets and send PN request for each of them.
1216 * Note that timeout already been set in ng_btsocket_rfcomm_connect()
1218 * Note: cannot use LIST_FOREACH because ng_btsocket_rfcomm_pcb_kill
1219 * will unlink DLC from the session
1222 for (pcb = LIST_FIRST(&s->dlcs); pcb != NULL; ) {
1223 mtx_lock(&pcb->pcb_mtx);
1224 pcb_next = LIST_NEXT(pcb, session_next);
1226 if (pcb->state == NG_BTSOCKET_RFCOMM_DLC_W4_CONNECT) {
1228 bcopy(&so2l2cap_pcb(s->l2so)->src, &pcb->src,
1231 error = ng_btsocket_rfcomm_send_pn(pcb);
1233 pcb->state = NG_BTSOCKET_RFCOMM_DLC_CONFIGURING;
1235 ng_btsocket_rfcomm_pcb_kill(pcb, error);
1238 mtx_unlock(&pcb->pcb_mtx);
1241 } /* ng_btsocket_rfcomm_connect_cfm */
1243 /*****************************************************************************
1244 *****************************************************************************
1246 *****************************************************************************
1247 *****************************************************************************/
1250 * Create new RFCOMM session. That function WILL NOT take ownership over l2so.
1251 * Caller MUST free l2so if function failed.
1255 ng_btsocket_rfcomm_session_create(ng_btsocket_rfcomm_session_p *sp,
1256 struct socket *l2so, bdaddr_p src, bdaddr_p dst,
1259 ng_btsocket_rfcomm_session_p s = NULL;
1260 struct sockaddr_l2cap l2sa;
1261 struct sockopt l2sopt;
1265 mtx_assert(&ng_btsocket_rfcomm_sessions_mtx, MA_OWNED);
1267 /* Allocate the RFCOMM session */
1268 MALLOC(s, ng_btsocket_rfcomm_session_p, sizeof(*s),
1269 M_NETGRAPH_BTSOCKET_RFCOMM, M_WAITOK | M_NULLOK | M_ZERO);
1274 s->mtu = RFCOMM_DEFAULT_MTU;
1276 s->state = NG_BTSOCKET_RFCOMM_SESSION_CLOSED;
1277 NG_BT_MBUFQ_INIT(&s->outq, ifqmaxlen);
1280 * XXX Mark session mutex as DUPOK to prevent "duplicated lock of
1281 * the same type" message. When accepting new L2CAP connection
1282 * ng_btsocket_rfcomm_session_accept() holds both session mutexes
1283 * for "old" (accepting) session and "new" (created) session.
1286 mtx_init(&s->session_mtx, "btsocks_rfcomm_session_mtx", NULL,
1289 LIST_INIT(&s->dlcs);
1291 /* Prepare L2CAP socket */
1292 l2so->so_upcallarg = NULL;
1293 l2so->so_upcall = ng_btsocket_rfcomm_upcall;
1294 SOCKBUF_LOCK(&l2so->so_rcv);
1295 l2so->so_rcv.sb_flags |= SB_UPCALL;
1296 SOCKBUF_UNLOCK(&l2so->so_rcv);
1297 SOCKBUF_LOCK(&l2so->so_snd);
1298 l2so->so_snd.sb_flags |= SB_UPCALL;
1299 SOCKBUF_UNLOCK(&l2so->so_snd);
1300 l2so->so_state |= SS_NBIO;
1303 mtx_lock(&s->session_mtx);
1306 * "src" == NULL and "dst" == NULL means just create session.
1307 * caller must do the rest
1310 if (src == NULL && dst == NULL)
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.
1319 mtu = s->mtu + sizeof(struct rfcomm_frame_hdr) + 1 + 1;
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;
1328 error = sosetopt(s->l2so, &l2sopt);
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));
1338 error = sobind(s->l2so, (struct sockaddr *) &l2sa, td);
1342 /* If "dst" is not NULL then initiate connect(), otherwise listen() */
1345 s->state = NG_BTSOCKET_RFCOMM_SESSION_LISTENING;
1347 error = solisten(s->l2so, 10, td);
1351 s->flags = NG_BTSOCKET_RFCOMM_SESSION_INITIATOR;
1352 s->state = NG_BTSOCKET_RFCOMM_SESSION_CONNECTING;
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));
1359 error = soconnect(s->l2so, (struct sockaddr *) &l2sa, td);
1365 LIST_INSERT_HEAD(&ng_btsocket_rfcomm_sessions, s, next);
1368 mtx_unlock(&s->session_mtx);
1373 mtx_unlock(&s->session_mtx);
1375 /* Return L2CAP socket back to its original state */
1376 l2so->so_upcallarg = NULL;
1377 l2so->so_upcall = NULL;
1378 SOCKBUF_LOCK(&l2so->so_rcv);
1379 l2so->so_rcv.sb_flags &= ~SB_UPCALL;
1380 SOCKBUF_UNLOCK(&l2so->so_rcv);
1381 SOCKBUF_LOCK(&l2so->so_snd);
1382 l2so->so_snd.sb_flags &= ~SB_UPCALL;
1383 SOCKBUF_UNLOCK(&l2so->so_snd);
1384 l2so->so_state &= ~SS_NBIO;
1386 mtx_destroy(&s->session_mtx);
1387 bzero(s, sizeof(*s));
1388 FREE(s, M_NETGRAPH_BTSOCKET_RFCOMM);
1391 } /* ng_btsocket_rfcomm_session_create */
1394 * Process accept() on RFCOMM session
1395 * XXX FIXME locking for "l2so"?
1399 ng_btsocket_rfcomm_session_accept(ng_btsocket_rfcomm_session_p s0)
1401 struct socket *l2so = NULL;
1402 struct sockaddr_l2cap *l2sa = NULL;
1403 ng_btsocket_l2cap_pcb_t *l2pcb = NULL;
1404 ng_btsocket_rfcomm_session_p s = NULL;
1407 mtx_assert(&ng_btsocket_rfcomm_sessions_mtx, MA_OWNED);
1408 mtx_assert(&s0->session_mtx, MA_OWNED);
1410 /* Check if there is a complete L2CAP connection in the queue */
1411 if ((error = s0->l2so->so_error) != 0) {
1412 NG_BTSOCKET_RFCOMM_ERR(
1413 "%s: Could not accept connection on L2CAP socket, error=%d\n", __func__, error);
1414 s0->l2so->so_error = 0;
1420 if (TAILQ_EMPTY(&s0->l2so->so_comp)) {
1422 if (s0->l2so->so_rcv.sb_state & SBS_CANTRCVMORE)
1423 return (ECONNABORTED);
1424 return (EWOULDBLOCK);
1427 /* Accept incoming L2CAP connection */
1428 l2so = TAILQ_FIRST(&s0->l2so->so_comp);
1430 panic("%s: l2so == NULL\n", __func__);
1432 TAILQ_REMOVE(&s0->l2so->so_comp, l2so, so_list);
1433 s0->l2so->so_qlen --;
1434 l2so->so_qstate &= ~SQ_COMP;
1435 l2so->so_head = NULL;
1438 l2so->so_state |= SS_NBIO;
1442 error = soaccept(l2so, (struct sockaddr **) &l2sa);
1444 NG_BTSOCKET_RFCOMM_ERR(
1445 "%s: soaccept() on L2CAP socket failed, error=%d\n", __func__, error);
1452 * Check if there is already active RFCOMM session between two devices.
1453 * If so then close L2CAP connection. We only support one RFCOMM session
1454 * between each pair of devices. Note that here we assume session in any
1455 * state. The session even could be in the middle of disconnecting.
1458 l2pcb = so2l2cap_pcb(l2so);
1459 s = ng_btsocket_rfcomm_session_by_addr(&l2pcb->src, &l2pcb->dst);
1461 /* Create a new RFCOMM session */
1462 error = ng_btsocket_rfcomm_session_create(&s, l2so, NULL, NULL,
1463 curthread /* XXX */);
1465 mtx_lock(&s->session_mtx);
1468 s->state = NG_BTSOCKET_RFCOMM_SESSION_CONNECTED;
1471 * Adjust MTU on incomming connection. Reserve 5 bytes:
1472 * RFCOMM frame header, one extra byte for length and
1473 * one extra byte for credits.
1476 s->mtu = min(l2pcb->imtu, l2pcb->omtu) -
1477 sizeof(struct rfcomm_frame_hdr) - 1 - 1;
1479 mtx_unlock(&s->session_mtx);
1481 NG_BTSOCKET_RFCOMM_ALERT(
1482 "%s: Failed to create new RFCOMM session, error=%d\n", __func__, error);
1487 NG_BTSOCKET_RFCOMM_WARN(
1488 "%s: Rejecting duplicating RFCOMM session between src=%x:%x:%x:%x:%x:%x and " \
1489 "dst=%x:%x:%x:%x:%x:%x, state=%d, flags=%#x\n", __func__,
1490 l2pcb->src.b[5], l2pcb->src.b[4], l2pcb->src.b[3],
1491 l2pcb->src.b[2], l2pcb->src.b[1], l2pcb->src.b[0],
1492 l2pcb->dst.b[5], l2pcb->dst.b[4], l2pcb->dst.b[3],
1493 l2pcb->dst.b[2], l2pcb->dst.b[1], l2pcb->dst.b[0],
1494 s->state, s->flags);
1501 } /* ng_btsocket_rfcomm_session_accept */
1504 * Process connect() on RFCOMM session
1505 * XXX FIXME locking for "l2so"?
1509 ng_btsocket_rfcomm_session_connect(ng_btsocket_rfcomm_session_p s)
1511 ng_btsocket_l2cap_pcb_p l2pcb = so2l2cap_pcb(s->l2so);
1514 mtx_assert(&s->session_mtx, MA_OWNED);
1516 /* First check if connection has failed */
1517 if ((error = s->l2so->so_error) != 0) {
1518 s->l2so->so_error = 0;
1520 NG_BTSOCKET_RFCOMM_ERR(
1521 "%s: Could not connect RFCOMM session, error=%d, state=%d, flags=%#x\n",
1522 __func__, error, s->state, s->flags);
1527 /* Is connection still in progress? */
1528 if (s->l2so->so_state & SS_ISCONNECTING)
1532 * If we got here then we are connected. Send SABM on DLCI 0 to
1533 * open multiplexor channel.
1537 s->state = NG_BTSOCKET_RFCOMM_SESSION_CONNECTED;
1540 * Adjust MTU on outgoing connection. Reserve 5 bytes: RFCOMM
1541 * frame header, one extra byte for length and one extra byte
1545 s->mtu = min(l2pcb->imtu, l2pcb->omtu) -
1546 sizeof(struct rfcomm_frame_hdr) - 1 - 1;
1548 error = ng_btsocket_rfcomm_send_command(s,RFCOMM_FRAME_SABM,0);
1550 error = ng_btsocket_rfcomm_task_wakeup();
1554 }/* ng_btsocket_rfcomm_session_connect */
1557 * Receive data on RFCOMM session
1558 * XXX FIXME locking for "l2so"?
1562 ng_btsocket_rfcomm_session_receive(ng_btsocket_rfcomm_session_p s)
1564 struct mbuf *m = NULL;
1566 int more, flags, error;
1568 mtx_assert(&s->session_mtx, MA_OWNED);
1570 /* Can we read from the L2CAP socket? */
1571 if (!soreadable(s->l2so))
1574 /* First check for error on L2CAP socket */
1575 if ((error = s->l2so->so_error) != 0) {
1576 s->l2so->so_error = 0;
1578 NG_BTSOCKET_RFCOMM_ERR(
1579 "%s: Could not receive data from L2CAP socket, error=%d, state=%d, flags=%#x\n",
1580 __func__, error, s->state, s->flags);
1586 * Read all packets from the L2CAP socket.
1587 * XXX FIXME/VERIFY is that correct? For now use m->m_nextpkt as
1588 * indication that there is more packets on the socket's buffer.
1589 * Also what should we use in uio.uio_resid?
1590 * May be s->mtu + sizeof(struct rfcomm_frame_hdr) + 1 + 1?
1593 for (more = 1; more; ) {
1594 /* Try to get next packet from socket */
1595 bzero(&uio, sizeof(uio));
1596 /* uio.uio_td = NULL; */
1597 uio.uio_resid = 1000000000;
1598 flags = MSG_DONTWAIT;
1601 error = soreceive(s->l2so, NULL, &uio, &m,
1602 (struct mbuf **) NULL, &flags);
1604 if (error == EWOULDBLOCK)
1605 return (0); /* XXX can happen? */
1607 NG_BTSOCKET_RFCOMM_ERR(
1608 "%s: Could not receive data from L2CAP socket, error=%d\n", __func__, error);
1613 more = (m->m_nextpkt != NULL);
1614 m->m_nextpkt = NULL;
1616 ng_btsocket_rfcomm_receive_frame(s, m);
1620 } /* ng_btsocket_rfcomm_session_receive */
1623 * Send data on RFCOMM session
1624 * XXX FIXME locking for "l2so"?
1628 ng_btsocket_rfcomm_session_send(ng_btsocket_rfcomm_session_p s)
1630 struct mbuf *m = NULL;
1633 mtx_assert(&s->session_mtx, MA_OWNED);
1635 /* Send as much as we can from the session queue */
1636 while (sowriteable(s->l2so)) {
1637 /* Check if socket still OK */
1638 if ((error = s->l2so->so_error) != 0) {
1639 s->l2so->so_error = 0;
1641 NG_BTSOCKET_RFCOMM_ERR(
1642 "%s: Detected error=%d on L2CAP socket, state=%d, flags=%#x\n",
1643 __func__, error, s->state, s->flags);
1648 NG_BT_MBUFQ_DEQUEUE(&s->outq, m);
1650 return (0); /* we are done */
1652 /* Call send function on the L2CAP socket */
1653 error = (*s->l2so->so_proto->pr_usrreqs->pru_send)(s->l2so,
1654 0, m, NULL, NULL, curthread /* XXX */);
1656 NG_BTSOCKET_RFCOMM_ERR(
1657 "%s: Could not send data to L2CAP socket, error=%d\n", __func__, error);
1664 } /* ng_btsocket_rfcomm_session_send */
1667 * Close and disconnect all DLCs for the given session. Caller must hold
1668 * s->sesson_mtx. Will wakeup session.
1672 ng_btsocket_rfcomm_session_clean(ng_btsocket_rfcomm_session_p s)
1674 ng_btsocket_rfcomm_pcb_p pcb = NULL, pcb_next = NULL;
1677 mtx_assert(&s->session_mtx, MA_OWNED);
1680 * Note: cannot use LIST_FOREACH because ng_btsocket_rfcomm_pcb_kill
1681 * will unlink DLC from the session
1684 for (pcb = LIST_FIRST(&s->dlcs); pcb != NULL; ) {
1685 mtx_lock(&pcb->pcb_mtx);
1686 pcb_next = LIST_NEXT(pcb, session_next);
1688 NG_BTSOCKET_RFCOMM_INFO(
1689 "%s: Disconnecting dlci=%d, state=%d, flags=%#x\n",
1690 __func__, pcb->dlci, pcb->state, pcb->flags);
1692 if (pcb->state == NG_BTSOCKET_RFCOMM_DLC_CONNECTED)
1695 error = ECONNREFUSED;
1697 ng_btsocket_rfcomm_pcb_kill(pcb, error);
1699 mtx_unlock(&pcb->pcb_mtx);
1702 } /* ng_btsocket_rfcomm_session_clean */
1705 * Process all DLCs on the session. Caller MUST hold s->session_mtx.
1709 ng_btsocket_rfcomm_session_process_pcb(ng_btsocket_rfcomm_session_p s)
1711 ng_btsocket_rfcomm_pcb_p pcb = NULL, pcb_next = NULL;
1714 mtx_assert(&s->session_mtx, MA_OWNED);
1717 * Note: cannot use LIST_FOREACH because ng_btsocket_rfcomm_pcb_kill
1718 * will unlink DLC from the session
1721 for (pcb = LIST_FIRST(&s->dlcs); pcb != NULL; ) {
1722 mtx_lock(&pcb->pcb_mtx);
1723 pcb_next = LIST_NEXT(pcb, session_next);
1725 switch (pcb->state) {
1728 * If DLC in W4_CONNECT state then we should check for both
1729 * timeout and detach.
1732 case NG_BTSOCKET_RFCOMM_DLC_W4_CONNECT:
1733 if (pcb->flags & NG_BTSOCKET_RFCOMM_DLC_DETACHED)
1734 ng_btsocket_rfcomm_pcb_kill(pcb, 0);
1735 else if (pcb->flags & NG_BTSOCKET_RFCOMM_DLC_TIMEDOUT)
1736 ng_btsocket_rfcomm_pcb_kill(pcb, ETIMEDOUT);
1740 * If DLC in CONFIGURING or CONNECTING state then we only
1741 * should check for timeout. If detach() was called then
1742 * DLC will be moved into DISCONNECTING state.
1745 case NG_BTSOCKET_RFCOMM_DLC_CONFIGURING:
1746 case NG_BTSOCKET_RFCOMM_DLC_CONNECTING:
1747 if (pcb->flags & NG_BTSOCKET_RFCOMM_DLC_TIMEDOUT)
1748 ng_btsocket_rfcomm_pcb_kill(pcb, ETIMEDOUT);
1752 * If DLC in CONNECTED state then we need to send data (if any)
1753 * from the socket's send queue. Note that we will send data
1754 * from either all sockets or none. This may overload session's
1755 * outgoing queue (but we do not check for that).
1757 * XXX FIXME need scheduler for RFCOMM sockets
1760 case NG_BTSOCKET_RFCOMM_DLC_CONNECTED:
1761 error = ng_btsocket_rfcomm_pcb_send(pcb, ALOT);
1763 ng_btsocket_rfcomm_pcb_kill(pcb, error);
1767 * If DLC in DISCONNECTING state then we must send DISC frame.
1768 * Note that if DLC has timeout set then we do not need to
1769 * resend DISC frame.
1771 * XXX FIXME need to drain all data from the socket's queue
1772 * if LINGER option was set
1775 case NG_BTSOCKET_RFCOMM_DLC_DISCONNECTING:
1776 if (!(pcb->flags & NG_BTSOCKET_RFCOMM_DLC_TIMO)) {
1777 error = ng_btsocket_rfcomm_send_command(
1778 pcb->session, RFCOMM_FRAME_DISC,
1781 ng_btsocket_rfcomm_timeout(pcb);
1783 ng_btsocket_rfcomm_pcb_kill(pcb, error);
1784 } else if (pcb->flags & NG_BTSOCKET_RFCOMM_DLC_TIMEDOUT)
1785 ng_btsocket_rfcomm_pcb_kill(pcb, ETIMEDOUT);
1788 /* case NG_BTSOCKET_RFCOMM_DLC_CLOSED: */
1790 panic("%s: Invalid DLC state=%d, flags=%#x\n",
1791 __func__, pcb->state, pcb->flags);
1795 mtx_unlock(&pcb->pcb_mtx);
1798 } /* ng_btsocket_rfcomm_session_process_pcb */
1801 * Find RFCOMM session between "src" and "dst".
1802 * Caller MUST hold ng_btsocket_rfcomm_sessions_mtx.
1805 static ng_btsocket_rfcomm_session_p
1806 ng_btsocket_rfcomm_session_by_addr(bdaddr_p src, bdaddr_p dst)
1808 ng_btsocket_rfcomm_session_p s = NULL;
1809 ng_btsocket_l2cap_pcb_p l2pcb = NULL;
1812 mtx_assert(&ng_btsocket_rfcomm_sessions_mtx, MA_OWNED);
1814 any_src = (bcmp(src, NG_HCI_BDADDR_ANY, sizeof(*src)) == 0);
1816 LIST_FOREACH(s, &ng_btsocket_rfcomm_sessions, next) {
1817 l2pcb = so2l2cap_pcb(s->l2so);
1819 if ((any_src || bcmp(&l2pcb->src, src, sizeof(*src)) == 0) &&
1820 bcmp(&l2pcb->dst, dst, sizeof(*dst)) == 0)
1825 } /* ng_btsocket_rfcomm_session_by_addr */
1827 /*****************************************************************************
1828 *****************************************************************************
1830 *****************************************************************************
1831 *****************************************************************************/
1834 * Process incoming RFCOMM frame. Caller must hold s->session_mtx.
1835 * XXX FIXME check frame length
1839 ng_btsocket_rfcomm_receive_frame(ng_btsocket_rfcomm_session_p s,
1842 struct rfcomm_frame_hdr *hdr = NULL;
1843 struct mbuf *m = NULL;
1845 u_int8_t dlci, type;
1848 mtx_assert(&s->session_mtx, MA_OWNED);
1850 /* Pullup as much as we can into first mbuf (for direct access) */
1851 length = min(m0->m_pkthdr.len, MHLEN);
1852 if (m0->m_len < length) {
1853 if ((m0 = m_pullup(m0, length)) == NULL) {
1854 NG_BTSOCKET_RFCOMM_ALERT(
1855 "%s: m_pullup(%d) failed\n", __func__, length);
1861 hdr = mtod(m0, struct rfcomm_frame_hdr *);
1862 dlci = RFCOMM_DLCI(hdr->address);
1863 type = RFCOMM_TYPE(hdr->control);
1865 /* Test EA bit in length. If not set then we have 2 bytes of length */
1866 if (!RFCOMM_EA(hdr->length)) {
1867 bcopy(&hdr->length, &length, sizeof(length));
1868 length = le16toh(length) >> 1;
1869 m_adj(m0, sizeof(*hdr) + 1);
1871 length = hdr->length >> 1;
1872 m_adj(m0, sizeof(*hdr));
1875 NG_BTSOCKET_RFCOMM_INFO(
1876 "%s: Got frame type=%#x, dlci=%d, length=%d, cr=%d, pf=%d, len=%d\n",
1877 __func__, type, dlci, length, RFCOMM_CR(hdr->address),
1878 RFCOMM_PF(hdr->control), m0->m_pkthdr.len);
1881 * Get FCS (the last byte in the frame)
1882 * XXX this will not work if mbuf chain ends with empty mbuf.
1883 * XXX let's hope it never happens :)
1886 for (m = m0; m->m_next != NULL; m = m->m_next)
1889 panic("%s: Empty mbuf at the end of the chain, len=%d\n",
1890 __func__, m->m_len);
1893 * Check FCS. We only need to calculate FCS on first 2 or 3 bytes
1894 * and already m_pullup'ed mbuf chain, so it should be safe.
1897 if (ng_btsocket_rfcomm_check_fcs((u_int8_t *) hdr, type, m->m_data[m->m_len - 1])) {
1898 NG_BTSOCKET_RFCOMM_ERR(
1899 "%s: Invalid RFCOMM packet. Bad checksum\n", __func__);
1905 m_adj(m0, -1); /* Trim FCS byte */
1908 * Process RFCOMM frame.
1910 * From TS 07.10 spec
1912 * "... In the case where a SABM or DISC command with the P bit set
1913 * to 0 is received then the received frame shall be discarded..."
1915 * "... If a unsolicited DM response is received then the frame shall
1916 * be processed irrespective of the P/F setting... "
1918 * "... The station may transmit response frames with the F bit set
1919 * to 0 at any opportunity on an asynchronous basis. However, in the
1920 * case where a UA response is received with the F bit set to 0 then
1921 * the received frame shall be discarded..."
1923 * From Bluetooth spec
1925 * "... When credit based flow control is being used, the meaning of
1926 * the P/F bit in the control field of the RFCOMM header is redefined
1927 * for UIH frames..."
1931 case RFCOMM_FRAME_SABM:
1932 if (RFCOMM_PF(hdr->control))
1933 error = ng_btsocket_rfcomm_receive_sabm(s, dlci);
1936 case RFCOMM_FRAME_DISC:
1937 if (RFCOMM_PF(hdr->control))
1938 error = ng_btsocket_rfcomm_receive_disc(s, dlci);
1941 case RFCOMM_FRAME_UA:
1942 if (RFCOMM_PF(hdr->control))
1943 error = ng_btsocket_rfcomm_receive_ua(s, dlci);
1946 case RFCOMM_FRAME_DM:
1947 error = ng_btsocket_rfcomm_receive_dm(s, dlci);
1950 case RFCOMM_FRAME_UIH:
1952 error = ng_btsocket_rfcomm_receive_mcc(s, m0);
1954 error = ng_btsocket_rfcomm_receive_uih(s, dlci,
1955 RFCOMM_PF(hdr->control), m0);
1961 NG_BTSOCKET_RFCOMM_ERR(
1962 "%s: Invalid RFCOMM packet. Unknown type=%#x\n", __func__, type);
1970 } /* ng_btsocket_rfcomm_receive_frame */
1973 * Process RFCOMM SABM frame
1977 ng_btsocket_rfcomm_receive_sabm(ng_btsocket_rfcomm_session_p s, int dlci)
1979 ng_btsocket_rfcomm_pcb_p pcb = NULL;
1982 mtx_assert(&s->session_mtx, MA_OWNED);
1984 NG_BTSOCKET_RFCOMM_INFO(
1985 "%s: Got SABM, session state=%d, flags=%#x, mtu=%d, dlci=%d\n",
1986 __func__, s->state, s->flags, s->mtu, dlci);
1988 /* DLCI == 0 means open multiplexor channel */
1991 case NG_BTSOCKET_RFCOMM_SESSION_CONNECTED:
1992 case NG_BTSOCKET_RFCOMM_SESSION_OPEN:
1993 error = ng_btsocket_rfcomm_send_command(s,
1994 RFCOMM_FRAME_UA, dlci);
1996 s->state = NG_BTSOCKET_RFCOMM_SESSION_OPEN;
1997 ng_btsocket_rfcomm_connect_cfm(s);
1999 s->state = NG_BTSOCKET_RFCOMM_SESSION_CLOSED;
2000 ng_btsocket_rfcomm_session_clean(s);
2005 NG_BTSOCKET_RFCOMM_WARN(
2006 "%s: Got SABM for session in invalid state state=%d, flags=%#x\n",
2007 __func__, s->state, s->flags);
2015 /* Make sure multiplexor channel is open */
2016 if (s->state != NG_BTSOCKET_RFCOMM_SESSION_OPEN) {
2017 NG_BTSOCKET_RFCOMM_ERR(
2018 "%s: Got SABM for dlci=%d with mulitplexor channel closed, state=%d, " \
2019 "flags=%#x\n", __func__, dlci, s->state, s->flags);
2025 * Check if we have this DLCI. This might happen when remote
2026 * peer uses PN command before actual open (SABM) happens.
2029 pcb = ng_btsocket_rfcomm_pcb_by_dlci(s, dlci);
2031 mtx_lock(&pcb->pcb_mtx);
2033 if (pcb->state != NG_BTSOCKET_RFCOMM_DLC_CONNECTING) {
2034 NG_BTSOCKET_RFCOMM_ERR(
2035 "%s: Got SABM for dlci=%d in invalid state=%d, flags=%#x\n",
2036 __func__, dlci, pcb->state, pcb->flags);
2037 mtx_unlock(&pcb->pcb_mtx);
2042 ng_btsocket_rfcomm_untimeout(pcb);
2044 error = ng_btsocket_rfcomm_send_command(s,RFCOMM_FRAME_UA,dlci);
2046 error = ng_btsocket_rfcomm_send_msc(pcb);
2049 pcb->state = NG_BTSOCKET_RFCOMM_DLC_CONNECTED;
2050 soisconnected(pcb->so);
2052 ng_btsocket_rfcomm_pcb_kill(pcb, error);
2054 mtx_unlock(&pcb->pcb_mtx);
2060 * We do not have requested DLCI, so it must be an incoming connection
2061 * with default parameters. Try to accept it.
2064 pcb = ng_btsocket_rfcomm_connect_ind(s, RFCOMM_SRVCHANNEL(dlci));
2066 mtx_lock(&pcb->pcb_mtx);
2070 error = ng_btsocket_rfcomm_send_command(s,RFCOMM_FRAME_UA,dlci);
2072 error = ng_btsocket_rfcomm_send_msc(pcb);
2075 pcb->state = NG_BTSOCKET_RFCOMM_DLC_CONNECTED;
2076 soisconnected(pcb->so);
2078 ng_btsocket_rfcomm_pcb_kill(pcb, error);
2080 mtx_unlock(&pcb->pcb_mtx);
2082 /* Nobody is listen()ing on the requested DLCI */
2083 error = ng_btsocket_rfcomm_send_command(s,RFCOMM_FRAME_DM,dlci);
2086 } /* ng_btsocket_rfcomm_receive_sabm */
2089 * Process RFCOMM DISC frame
2093 ng_btsocket_rfcomm_receive_disc(ng_btsocket_rfcomm_session_p s, int dlci)
2095 ng_btsocket_rfcomm_pcb_p pcb = NULL;
2098 mtx_assert(&s->session_mtx, MA_OWNED);
2100 NG_BTSOCKET_RFCOMM_INFO(
2101 "%s: Got DISC, session state=%d, flags=%#x, mtu=%d, dlci=%d\n",
2102 __func__, s->state, s->flags, s->mtu, dlci);
2104 /* DLCI == 0 means close multiplexor channel */
2106 /* XXX FIXME assume that remote side will close the socket */
2107 error = ng_btsocket_rfcomm_send_command(s, RFCOMM_FRAME_UA, 0);
2109 if (s->state == NG_BTSOCKET_RFCOMM_SESSION_DISCONNECTING)
2110 s->state = NG_BTSOCKET_RFCOMM_SESSION_CLOSED; /* XXX */
2112 s->state = NG_BTSOCKET_RFCOMM_SESSION_DISCONNECTING;
2114 s->state = NG_BTSOCKET_RFCOMM_SESSION_CLOSED; /* XXX */
2116 ng_btsocket_rfcomm_session_clean(s);
2118 pcb = ng_btsocket_rfcomm_pcb_by_dlci(s, dlci);
2122 mtx_lock(&pcb->pcb_mtx);
2124 NG_BTSOCKET_RFCOMM_INFO(
2125 "%s: Got DISC for dlci=%d, state=%d, flags=%#x\n",
2126 __func__, dlci, pcb->state, pcb->flags);
2128 error = ng_btsocket_rfcomm_send_command(s,
2129 RFCOMM_FRAME_UA, dlci);
2131 if (pcb->state == NG_BTSOCKET_RFCOMM_DLC_CONNECTED)
2136 ng_btsocket_rfcomm_pcb_kill(pcb, err);
2138 mtx_unlock(&pcb->pcb_mtx);
2140 NG_BTSOCKET_RFCOMM_WARN(
2141 "%s: Got DISC for non-existing dlci=%d\n", __func__, dlci);
2143 error = ng_btsocket_rfcomm_send_command(s,
2144 RFCOMM_FRAME_DM, dlci);
2149 } /* ng_btsocket_rfcomm_receive_disc */
2152 * Process RFCOMM UA frame
2156 ng_btsocket_rfcomm_receive_ua(ng_btsocket_rfcomm_session_p s, int dlci)
2158 ng_btsocket_rfcomm_pcb_p pcb = NULL;
2161 mtx_assert(&s->session_mtx, MA_OWNED);
2163 NG_BTSOCKET_RFCOMM_INFO(
2164 "%s: Got UA, session state=%d, flags=%#x, mtu=%d, dlci=%d\n",
2165 __func__, s->state, s->flags, s->mtu, dlci);
2167 /* dlci == 0 means multiplexor channel */
2170 case NG_BTSOCKET_RFCOMM_SESSION_CONNECTED:
2171 s->state = NG_BTSOCKET_RFCOMM_SESSION_OPEN;
2172 ng_btsocket_rfcomm_connect_cfm(s);
2175 case NG_BTSOCKET_RFCOMM_SESSION_DISCONNECTING:
2176 s->state = NG_BTSOCKET_RFCOMM_SESSION_CLOSED;
2177 ng_btsocket_rfcomm_session_clean(s);
2181 NG_BTSOCKET_RFCOMM_WARN(
2182 "%s: Got UA for session in invalid state=%d(%d), flags=%#x, mtu=%d\n",
2183 __func__, s->state, INITIATOR(s), s->flags,
2192 /* Check if we have this DLCI */
2193 pcb = ng_btsocket_rfcomm_pcb_by_dlci(s, dlci);
2195 mtx_lock(&pcb->pcb_mtx);
2197 NG_BTSOCKET_RFCOMM_INFO(
2198 "%s: Got UA for dlci=%d, state=%d, flags=%#x\n",
2199 __func__, dlci, pcb->state, pcb->flags);
2201 switch (pcb->state) {
2202 case NG_BTSOCKET_RFCOMM_DLC_CONNECTING:
2203 ng_btsocket_rfcomm_untimeout(pcb);
2205 error = ng_btsocket_rfcomm_send_msc(pcb);
2207 pcb->state = NG_BTSOCKET_RFCOMM_DLC_CONNECTED;
2208 soisconnected(pcb->so);
2212 case NG_BTSOCKET_RFCOMM_DLC_DISCONNECTING:
2213 ng_btsocket_rfcomm_pcb_kill(pcb, 0);
2217 NG_BTSOCKET_RFCOMM_WARN(
2218 "%s: Got UA for dlci=%d in invalid state=%d, flags=%#x\n",
2219 __func__, dlci, pcb->state, pcb->flags);
2224 mtx_unlock(&pcb->pcb_mtx);
2226 NG_BTSOCKET_RFCOMM_WARN(
2227 "%s: Got UA for non-existing dlci=%d\n", __func__, dlci);
2229 error = ng_btsocket_rfcomm_send_command(s,RFCOMM_FRAME_DM,dlci);
2233 } /* ng_btsocket_rfcomm_receive_ua */
2236 * Process RFCOMM DM frame
2240 ng_btsocket_rfcomm_receive_dm(ng_btsocket_rfcomm_session_p s, int dlci)
2242 ng_btsocket_rfcomm_pcb_p pcb = NULL;
2245 mtx_assert(&s->session_mtx, MA_OWNED);
2247 NG_BTSOCKET_RFCOMM_INFO(
2248 "%s: Got DM, session state=%d, flags=%#x, mtu=%d, dlci=%d\n",
2249 __func__, s->state, s->flags, s->mtu, dlci);
2251 /* DLCI == 0 means multiplexor channel */
2253 /* Disconnect all dlc's on the session */
2254 s->state = NG_BTSOCKET_RFCOMM_SESSION_CLOSED;
2255 ng_btsocket_rfcomm_session_clean(s);
2257 pcb = ng_btsocket_rfcomm_pcb_by_dlci(s, dlci);
2259 mtx_lock(&pcb->pcb_mtx);
2261 NG_BTSOCKET_RFCOMM_INFO(
2262 "%s: Got DM for dlci=%d, state=%d, flags=%#x\n",
2263 __func__, dlci, pcb->state, pcb->flags);
2265 if (pcb->state == NG_BTSOCKET_RFCOMM_DLC_CONNECTED)
2268 error = ECONNREFUSED;
2270 ng_btsocket_rfcomm_pcb_kill(pcb, error);
2272 mtx_unlock(&pcb->pcb_mtx);
2274 NG_BTSOCKET_RFCOMM_WARN(
2275 "%s: Got DM for non-existing dlci=%d\n", __func__, dlci);
2279 } /* ng_btsocket_rfcomm_receive_dm */
2282 * Process RFCOMM UIH frame (data)
2286 ng_btsocket_rfcomm_receive_uih(ng_btsocket_rfcomm_session_p s, int dlci,
2287 int pf, struct mbuf *m0)
2289 ng_btsocket_rfcomm_pcb_p pcb = NULL;
2292 mtx_assert(&s->session_mtx, MA_OWNED);
2294 NG_BTSOCKET_RFCOMM_INFO(
2295 "%s: Got UIH, session state=%d, flags=%#x, mtu=%d, dlci=%d, pf=%d, len=%d\n",
2296 __func__, s->state, s->flags, s->mtu, dlci, pf,
2299 /* XXX should we do it here? Check for session flow control */
2300 if (s->flags & NG_BTSOCKET_RFCOMM_SESSION_LFC) {
2301 NG_BTSOCKET_RFCOMM_WARN(
2302 "%s: Got UIH with session flow control asserted, state=%d, flags=%#x\n",
2303 __func__, s->state, s->flags);
2307 /* Check if we have this dlci */
2308 pcb = ng_btsocket_rfcomm_pcb_by_dlci(s, dlci);
2310 NG_BTSOCKET_RFCOMM_WARN(
2311 "%s: Got UIH for non-existing dlci=%d\n", __func__, dlci);
2312 error = ng_btsocket_rfcomm_send_command(s,RFCOMM_FRAME_DM,dlci);
2316 mtx_lock(&pcb->pcb_mtx);
2318 /* Check dlci state */
2319 if (pcb->state != NG_BTSOCKET_RFCOMM_DLC_CONNECTED) {
2320 NG_BTSOCKET_RFCOMM_WARN(
2321 "%s: Got UIH for dlci=%d in invalid state=%d, flags=%#x\n",
2322 __func__, dlci, pcb->state, pcb->flags);
2327 /* Check dlci flow control */
2328 if (((pcb->flags & NG_BTSOCKET_RFCOMM_DLC_CFC) && pcb->rx_cred <= 0) ||
2329 (pcb->lmodem & RFCOMM_MODEM_FC)) {
2330 NG_BTSOCKET_RFCOMM_ERR(
2331 "%s: Got UIH for dlci=%d with asserted flow control, state=%d, " \
2332 "flags=%#x, rx_cred=%d, lmodem=%#x\n",
2333 __func__, dlci, pcb->state, pcb->flags,
2334 pcb->rx_cred, pcb->lmodem);
2338 /* Did we get any credits? */
2339 if ((pcb->flags & NG_BTSOCKET_RFCOMM_DLC_CFC) && pf) {
2340 NG_BTSOCKET_RFCOMM_INFO(
2341 "%s: Got %d more credits for dlci=%d, state=%d, flags=%#x, " \
2342 "rx_cred=%d, tx_cred=%d\n",
2343 __func__, *mtod(m0, u_int8_t *), dlci, pcb->state,
2344 pcb->flags, pcb->rx_cred, pcb->tx_cred);
2346 pcb->tx_cred += *mtod(m0, u_int8_t *);
2349 /* Send more from the DLC. XXX check for errors? */
2350 ng_btsocket_rfcomm_pcb_send(pcb, ALOT);
2353 /* OK the of the rest of the mbuf is the data */
2354 if (m0->m_pkthdr.len > 0) {
2355 /* If we are using credit flow control decrease rx_cred here */
2356 if (pcb->flags & NG_BTSOCKET_RFCOMM_DLC_CFC) {
2357 /* Give remote peer more credits (if needed) */
2358 if (-- pcb->rx_cred <= RFCOMM_MAX_CREDITS / 2)
2359 ng_btsocket_rfcomm_send_credits(pcb);
2361 NG_BTSOCKET_RFCOMM_INFO(
2362 "%s: Remote side still has credits, dlci=%d, state=%d, flags=%#x, " \
2363 "rx_cred=%d, tx_cred=%d\n", __func__, dlci, pcb->state, pcb->flags,
2364 pcb->rx_cred, pcb->tx_cred);
2367 /* Check packet against mtu on dlci */
2368 if (m0->m_pkthdr.len > pcb->mtu) {
2369 NG_BTSOCKET_RFCOMM_ERR(
2370 "%s: Got oversized UIH for dlci=%d, state=%d, flags=%#x, mtu=%d, len=%d\n",
2371 __func__, dlci, pcb->state, pcb->flags,
2372 pcb->mtu, m0->m_pkthdr.len);
2375 } else if (m0->m_pkthdr.len > sbspace(&pcb->so->so_rcv)) {
2378 * This is really bad. Receive queue on socket does
2379 * not have enough space for the packet. We do not
2380 * have any other choice but drop the packet.
2383 NG_BTSOCKET_RFCOMM_ERR(
2384 "%s: Not enough space in socket receive queue. Dropping UIH for dlci=%d, " \
2385 "state=%d, flags=%#x, len=%d, space=%ld\n",
2386 __func__, dlci, pcb->state, pcb->flags,
2387 m0->m_pkthdr.len, sbspace(&pcb->so->so_rcv));
2391 /* Append packet to the socket receive queue */
2392 sbappend(&pcb->so->so_rcv, m0);
2399 mtx_unlock(&pcb->pcb_mtx);
2401 NG_FREE_M(m0); /* checks for != NULL */
2404 } /* ng_btsocket_rfcomm_receive_uih */
2407 * Process RFCOMM MCC command (Multiplexor)
2409 * From TS 07.10 spec
2411 * "5.4.3.1 Information Data
2413 * ...The frames (UIH) sent by the initiating station have the C/R bit set
2414 * to 1 and those sent by the responding station have the C/R bit set to 0..."
2416 * "5.4.6.2 Operating procedures
2418 * Messages always exist in pairs; a command message and a corresponding
2419 * response message. If the C/R bit is set to 1 the message is a command,
2420 * if it is set to 0 the message is a response...
2424 * NOTE: Notice that when UIH frames are used to convey information on DLCI 0
2425 * there are at least two different fields that contain a C/R bit, and the
2426 * bits are set of different form. The C/R bit in the Type field shall be set
2427 * as it is stated above, while the C/R bit in the Address field (see subclause
2428 * 5.2.1.2) shall be set as it is described in subclause 5.4.3.1."
2432 ng_btsocket_rfcomm_receive_mcc(ng_btsocket_rfcomm_session_p s, struct mbuf *m0)
2434 struct rfcomm_mcc_hdr *hdr = NULL;
2435 u_int8_t cr, type, length;
2437 mtx_assert(&s->session_mtx, MA_OWNED);
2440 * We can access data directly in the first mbuf, because we have
2441 * m_pullup()'ed mbuf chain in ng_btsocket_rfcomm_receive_frame().
2442 * All MCC commands should fit into single mbuf (except probably TEST).
2445 hdr = mtod(m0, struct rfcomm_mcc_hdr *);
2446 cr = RFCOMM_CR(hdr->type);
2447 type = RFCOMM_MCC_TYPE(hdr->type);
2448 length = RFCOMM_MCC_LENGTH(hdr->length);
2450 /* Check MCC frame length */
2451 if (sizeof(*hdr) + length != m0->m_pkthdr.len) {
2452 NG_BTSOCKET_RFCOMM_ERR(
2453 "%s: Invalid MCC frame length=%d, len=%d\n",
2454 __func__, length, m0->m_pkthdr.len);
2461 case RFCOMM_MCC_TEST:
2462 return (ng_btsocket_rfcomm_receive_test(s, m0));
2465 case RFCOMM_MCC_FCON:
2466 case RFCOMM_MCC_FCOFF:
2467 return (ng_btsocket_rfcomm_receive_fc(s, m0));
2470 case RFCOMM_MCC_MSC:
2471 return (ng_btsocket_rfcomm_receive_msc(s, m0));
2474 case RFCOMM_MCC_RPN:
2475 return (ng_btsocket_rfcomm_receive_rpn(s, m0));
2478 case RFCOMM_MCC_RLS:
2479 return (ng_btsocket_rfcomm_receive_rls(s, m0));
2483 return (ng_btsocket_rfcomm_receive_pn(s, m0));
2486 case RFCOMM_MCC_NSC:
2487 NG_BTSOCKET_RFCOMM_ERR(
2488 "%s: Got MCC NSC, type=%#x, cr=%d, length=%d, session state=%d, flags=%#x, " \
2489 "mtu=%d, len=%d\n", __func__, RFCOMM_MCC_TYPE(*((u_int8_t *)(hdr + 1))), cr,
2490 length, s->state, s->flags, s->mtu, m0->m_pkthdr.len);
2495 NG_BTSOCKET_RFCOMM_ERR(
2496 "%s: Got unknown MCC, type=%#x, cr=%d, length=%d, session state=%d, " \
2497 "flags=%#x, mtu=%d, len=%d\n",
2498 __func__, type, cr, length, s->state, s->flags,
2499 s->mtu, m0->m_pkthdr.len);
2501 /* Reuse mbuf to send NSC */
2502 hdr = mtod(m0, struct rfcomm_mcc_hdr *);
2503 m0->m_pkthdr.len = m0->m_len = sizeof(*hdr);
2505 /* Create MCC NSC header */
2506 hdr->type = RFCOMM_MKMCC_TYPE(0, RFCOMM_MCC_NSC);
2507 hdr->length = RFCOMM_MKLEN8(1);
2509 /* Put back MCC command type we did not like */
2510 m0->m_data[m0->m_len] = RFCOMM_MKMCC_TYPE(cr, type);
2511 m0->m_pkthdr.len ++;
2514 /* Send UIH frame */
2515 return (ng_btsocket_rfcomm_send_uih(s,
2516 RFCOMM_MKADDRESS(INITIATOR(s), 0), 0, 0, m0));
2521 } /* ng_btsocket_rfcomm_receive_mcc */
2524 * Receive RFCOMM TEST MCC command
2528 ng_btsocket_rfcomm_receive_test(ng_btsocket_rfcomm_session_p s, struct mbuf *m0)
2530 struct rfcomm_mcc_hdr *hdr = mtod(m0, struct rfcomm_mcc_hdr *);
2533 mtx_assert(&s->session_mtx, MA_OWNED);
2535 NG_BTSOCKET_RFCOMM_INFO(
2536 "%s: Got MCC TEST, cr=%d, length=%d, session state=%d, flags=%#x, mtu=%d, " \
2537 "len=%d\n", __func__, RFCOMM_CR(hdr->type), RFCOMM_MCC_LENGTH(hdr->length),
2538 s->state, s->flags, s->mtu, m0->m_pkthdr.len);
2540 if (RFCOMM_CR(hdr->type)) {
2541 hdr->type = RFCOMM_MKMCC_TYPE(0, RFCOMM_MCC_TEST);
2542 error = ng_btsocket_rfcomm_send_uih(s,
2543 RFCOMM_MKADDRESS(INITIATOR(s), 0), 0, 0, m0);
2545 NG_FREE_M(m0); /* XXX ignore response */
2548 } /* ng_btsocket_rfcomm_receive_test */
2551 * Receive RFCOMM FCON/FCOFF MCC command
2555 ng_btsocket_rfcomm_receive_fc(ng_btsocket_rfcomm_session_p s, struct mbuf *m0)
2557 struct rfcomm_mcc_hdr *hdr = mtod(m0, struct rfcomm_mcc_hdr *);
2558 u_int8_t type = RFCOMM_MCC_TYPE(hdr->type);
2561 mtx_assert(&s->session_mtx, MA_OWNED);
2564 * Turn ON/OFF aggregate flow on the entire session. When remote peer
2565 * asserted flow control no transmission shall occur except on dlci 0
2566 * (control channel).
2569 NG_BTSOCKET_RFCOMM_INFO(
2570 "%s: Got MCC FC%s, cr=%d, length=%d, session state=%d, flags=%#x, mtu=%d, " \
2571 "len=%d\n", __func__, (type == RFCOMM_MCC_FCON)? "ON" : "OFF",
2572 RFCOMM_CR(hdr->type), RFCOMM_MCC_LENGTH(hdr->length),
2573 s->state, s->flags, s->mtu, m0->m_pkthdr.len);
2575 if (RFCOMM_CR(hdr->type)) {
2576 if (type == RFCOMM_MCC_FCON)
2577 s->flags &= ~NG_BTSOCKET_RFCOMM_SESSION_RFC;
2579 s->flags |= NG_BTSOCKET_RFCOMM_SESSION_RFC;
2581 hdr->type = RFCOMM_MKMCC_TYPE(0, type);
2582 error = ng_btsocket_rfcomm_send_uih(s,
2583 RFCOMM_MKADDRESS(INITIATOR(s), 0), 0, 0, m0);
2585 NG_FREE_M(m0); /* XXX ignore response */
2588 } /* ng_btsocket_rfcomm_receive_fc */
2591 * Receive RFCOMM MSC MCC command
2595 ng_btsocket_rfcomm_receive_msc(ng_btsocket_rfcomm_session_p s, struct mbuf *m0)
2597 struct rfcomm_mcc_hdr *hdr = mtod(m0, struct rfcomm_mcc_hdr*);
2598 struct rfcomm_mcc_msc *msc = (struct rfcomm_mcc_msc *)(hdr+1);
2599 ng_btsocket_rfcomm_pcb_t *pcb = NULL;
2602 mtx_assert(&s->session_mtx, MA_OWNED);
2604 NG_BTSOCKET_RFCOMM_INFO(
2605 "%s: Got MCC MSC, dlci=%d, cr=%d, length=%d, session state=%d, flags=%#x, " \
2607 __func__, RFCOMM_DLCI(msc->address), RFCOMM_CR(hdr->type),
2608 RFCOMM_MCC_LENGTH(hdr->length), s->state, s->flags,
2609 s->mtu, m0->m_pkthdr.len);
2611 if (RFCOMM_CR(hdr->type)) {
2612 pcb = ng_btsocket_rfcomm_pcb_by_dlci(s, RFCOMM_DLCI(msc->address));
2614 NG_BTSOCKET_RFCOMM_WARN(
2615 "%s: Got MSC command for non-existing dlci=%d\n",
2616 __func__, RFCOMM_DLCI(msc->address));
2622 mtx_lock(&pcb->pcb_mtx);
2624 if (pcb->state != NG_BTSOCKET_RFCOMM_DLC_CONNECTING &&
2625 pcb->state != NG_BTSOCKET_RFCOMM_DLC_CONNECTED) {
2626 NG_BTSOCKET_RFCOMM_WARN(
2627 "%s: Got MSC on dlci=%d in invalid state=%d\n",
2628 __func__, RFCOMM_DLCI(msc->address),
2631 mtx_unlock(&pcb->pcb_mtx);
2637 pcb->rmodem = msc->modem; /* Update remote port signals */
2639 hdr->type = RFCOMM_MKMCC_TYPE(0, RFCOMM_MCC_MSC);
2640 error = ng_btsocket_rfcomm_send_uih(s,
2641 RFCOMM_MKADDRESS(INITIATOR(s), 0), 0, 0, m0);
2644 /* Send more data from DLC. XXX check for errors? */
2645 if (!(pcb->rmodem & RFCOMM_MODEM_FC) &&
2646 !(pcb->flags & NG_BTSOCKET_RFCOMM_DLC_CFC))
2647 ng_btsocket_rfcomm_pcb_send(pcb, ALOT);
2650 mtx_unlock(&pcb->pcb_mtx);
2652 NG_FREE_M(m0); /* XXX ignore response */
2655 } /* ng_btsocket_rfcomm_receive_msc */
2658 * Receive RFCOMM RPN MCC command
2659 * XXX FIXME do we need htole16/le16toh for RPN param_mask?
2663 ng_btsocket_rfcomm_receive_rpn(ng_btsocket_rfcomm_session_p s, struct mbuf *m0)
2665 struct rfcomm_mcc_hdr *hdr = mtod(m0, struct rfcomm_mcc_hdr *);
2666 struct rfcomm_mcc_rpn *rpn = (struct rfcomm_mcc_rpn *)(hdr + 1);
2668 u_int16_t param_mask;
2669 u_int8_t bit_rate, data_bits, stop_bits, parity,
2670 flow_control, xon_char, xoff_char;
2672 mtx_assert(&s->session_mtx, MA_OWNED);
2674 NG_BTSOCKET_RFCOMM_INFO(
2675 "%s: Got MCC RPN, dlci=%d, cr=%d, length=%d, session state=%d, flags=%#x, " \
2677 __func__, RFCOMM_DLCI(rpn->dlci), RFCOMM_CR(hdr->type),
2678 RFCOMM_MCC_LENGTH(hdr->length), s->state, s->flags,
2679 s->mtu, m0->m_pkthdr.len);
2681 if (RFCOMM_CR(hdr->type)) {
2682 param_mask = RFCOMM_RPN_PM_ALL;
2684 if (RFCOMM_MCC_LENGTH(hdr->length) == 1) {
2685 /* Request - return default setting */
2686 bit_rate = RFCOMM_RPN_BR_115200;
2687 data_bits = RFCOMM_RPN_DATA_8;
2688 stop_bits = RFCOMM_RPN_STOP_1;
2689 parity = RFCOMM_RPN_PARITY_NONE;
2690 flow_control = RFCOMM_RPN_FLOW_NONE;
2691 xon_char = RFCOMM_RPN_XON_CHAR;
2692 xoff_char = RFCOMM_RPN_XOFF_CHAR;
2695 * Ignore/accept bit_rate, 8 bits, 1 stop bit, no
2696 * parity, no flow control lines, default XON/XOFF
2700 bit_rate = rpn->bit_rate;
2701 rpn->param_mask = le16toh(rpn->param_mask); /* XXX */
2703 data_bits = RFCOMM_RPN_DATA_BITS(rpn->line_settings);
2704 if (rpn->param_mask & RFCOMM_RPN_PM_DATA &&
2705 data_bits != RFCOMM_RPN_DATA_8) {
2706 data_bits = RFCOMM_RPN_DATA_8;
2707 param_mask ^= RFCOMM_RPN_PM_DATA;
2710 stop_bits = RFCOMM_RPN_STOP_BITS(rpn->line_settings);
2711 if (rpn->param_mask & RFCOMM_RPN_PM_STOP &&
2712 stop_bits != RFCOMM_RPN_STOP_1) {
2713 stop_bits = RFCOMM_RPN_STOP_1;
2714 param_mask ^= RFCOMM_RPN_PM_STOP;
2717 parity = RFCOMM_RPN_PARITY(rpn->line_settings);
2718 if (rpn->param_mask & RFCOMM_RPN_PM_PARITY &&
2719 parity != RFCOMM_RPN_PARITY_NONE) {
2720 parity = RFCOMM_RPN_PARITY_NONE;
2721 param_mask ^= RFCOMM_RPN_PM_PARITY;
2724 flow_control = rpn->flow_control;
2725 if (rpn->param_mask & RFCOMM_RPN_PM_FLOW &&
2726 flow_control != RFCOMM_RPN_FLOW_NONE) {
2727 flow_control = RFCOMM_RPN_FLOW_NONE;
2728 param_mask ^= RFCOMM_RPN_PM_FLOW;
2731 xon_char = rpn->xon_char;
2732 if (rpn->param_mask & RFCOMM_RPN_PM_XON &&
2733 xon_char != RFCOMM_RPN_XON_CHAR) {
2734 xon_char = RFCOMM_RPN_XON_CHAR;
2735 param_mask ^= RFCOMM_RPN_PM_XON;
2738 xoff_char = rpn->xoff_char;
2739 if (rpn->param_mask & RFCOMM_RPN_PM_XOFF &&
2740 xoff_char != RFCOMM_RPN_XOFF_CHAR) {
2741 xoff_char = RFCOMM_RPN_XOFF_CHAR;
2742 param_mask ^= RFCOMM_RPN_PM_XOFF;
2746 rpn->bit_rate = bit_rate;
2747 rpn->line_settings = RFCOMM_MKRPN_LINE_SETTINGS(data_bits,
2749 rpn->flow_control = flow_control;
2750 rpn->xon_char = xon_char;
2751 rpn->xoff_char = xoff_char;
2752 rpn->param_mask = htole16(param_mask); /* XXX */
2754 m0->m_pkthdr.len = m0->m_len = sizeof(*hdr) + sizeof(*rpn);
2756 hdr->type = RFCOMM_MKMCC_TYPE(0, RFCOMM_MCC_RPN);
2757 error = ng_btsocket_rfcomm_send_uih(s,
2758 RFCOMM_MKADDRESS(INITIATOR(s), 0), 0, 0, m0);
2760 NG_FREE_M(m0); /* XXX ignore response */
2763 } /* ng_btsocket_rfcomm_receive_rpn */
2766 * Receive RFCOMM RLS MCC command
2770 ng_btsocket_rfcomm_receive_rls(ng_btsocket_rfcomm_session_p s, struct mbuf *m0)
2772 struct rfcomm_mcc_hdr *hdr = mtod(m0, struct rfcomm_mcc_hdr *);
2773 struct rfcomm_mcc_rls *rls = (struct rfcomm_mcc_rls *)(hdr + 1);
2776 mtx_assert(&s->session_mtx, MA_OWNED);
2779 * XXX FIXME Do we have to do anything else here? Remote peer tries to
2780 * tell us something about DLCI. Just report what we have received and
2781 * return back received values as required by TS 07.10 spec.
2784 NG_BTSOCKET_RFCOMM_INFO(
2785 "%s: Got MCC RLS, dlci=%d, status=%#x, cr=%d, length=%d, session state=%d, " \
2786 "flags=%#x, mtu=%d, len=%d\n",
2787 __func__, RFCOMM_DLCI(rls->address), rls->status,
2788 RFCOMM_CR(hdr->type), RFCOMM_MCC_LENGTH(hdr->length),
2789 s->state, s->flags, s->mtu, m0->m_pkthdr.len);
2791 if (RFCOMM_CR(hdr->type)) {
2792 if (rls->status & 0x1)
2793 NG_BTSOCKET_RFCOMM_ERR(
2794 "%s: Got RLS dlci=%d, error=%#x\n", __func__, RFCOMM_DLCI(rls->address),
2797 hdr->type = RFCOMM_MKMCC_TYPE(0, RFCOMM_MCC_RLS);
2798 error = ng_btsocket_rfcomm_send_uih(s,
2799 RFCOMM_MKADDRESS(INITIATOR(s), 0), 0, 0, m0);
2801 NG_FREE_M(m0); /* XXX ignore responses */
2804 } /* ng_btsocket_rfcomm_receive_rls */
2807 * Receive RFCOMM PN MCC command
2811 ng_btsocket_rfcomm_receive_pn(ng_btsocket_rfcomm_session_p s, struct mbuf *m0)
2813 struct rfcomm_mcc_hdr *hdr = mtod(m0, struct rfcomm_mcc_hdr*);
2814 struct rfcomm_mcc_pn *pn = (struct rfcomm_mcc_pn *)(hdr+1);
2815 ng_btsocket_rfcomm_pcb_t *pcb = NULL;
2818 mtx_assert(&s->session_mtx, MA_OWNED);
2820 NG_BTSOCKET_RFCOMM_INFO(
2821 "%s: Got MCC PN, dlci=%d, cr=%d, length=%d, flow_control=%#x, priority=%d, " \
2822 "ack_timer=%d, mtu=%d, max_retrans=%d, credits=%d, session state=%d, " \
2823 "flags=%#x, session mtu=%d, len=%d\n",
2824 __func__, pn->dlci, RFCOMM_CR(hdr->type),
2825 RFCOMM_MCC_LENGTH(hdr->length), pn->flow_control, pn->priority,
2826 pn->ack_timer, le16toh(pn->mtu), pn->max_retrans, pn->credits,
2827 s->state, s->flags, s->mtu, m0->m_pkthdr.len);
2829 if (pn->dlci == 0) {
2830 NG_BTSOCKET_RFCOMM_ERR("%s: Zero dlci in MCC PN\n", __func__);
2836 /* Check if we have this dlci */
2837 pcb = ng_btsocket_rfcomm_pcb_by_dlci(s, pn->dlci);
2839 mtx_lock(&pcb->pcb_mtx);
2841 if (RFCOMM_CR(hdr->type)) {
2843 ng_btsocket_rfcomm_set_pn(pcb, 1, pn->flow_control,
2844 pn->credits, pn->mtu);
2846 if (pcb->flags & NG_BTSOCKET_RFCOMM_DLC_CFC) {
2847 pn->flow_control = 0xe0;
2848 pn->credits = RFCOMM_DEFAULT_CREDITS;
2850 pn->flow_control = 0;
2854 hdr->type = RFCOMM_MKMCC_TYPE(0, RFCOMM_MCC_PN);
2855 error = ng_btsocket_rfcomm_send_uih(s,
2856 RFCOMM_MKADDRESS(INITIATOR(s), 0),
2859 /* PN Response - proceed with SABM. Timeout still set */
2860 if (pcb->state == NG_BTSOCKET_RFCOMM_DLC_CONFIGURING) {
2861 ng_btsocket_rfcomm_set_pn(pcb, 0,
2862 pn->flow_control, pn->credits, pn->mtu);
2864 pcb->state = NG_BTSOCKET_RFCOMM_DLC_CONNECTING;
2865 error = ng_btsocket_rfcomm_send_command(s,
2866 RFCOMM_FRAME_SABM, pn->dlci);
2868 NG_BTSOCKET_RFCOMM_WARN(
2869 "%s: Got PN response for dlci=%d in invalid state=%d\n",
2870 __func__, pn->dlci, pcb->state);
2875 mtx_unlock(&pcb->pcb_mtx);
2876 } else if (RFCOMM_CR(hdr->type)) {
2877 /* PN request to non-existing dlci - incomming connection */
2878 pcb = ng_btsocket_rfcomm_connect_ind(s,
2879 RFCOMM_SRVCHANNEL(pn->dlci));
2881 mtx_lock(&pcb->pcb_mtx);
2883 pcb->dlci = pn->dlci;
2885 ng_btsocket_rfcomm_set_pn(pcb, 1, pn->flow_control,
2886 pn->credits, pn->mtu);
2888 if (pcb->flags & NG_BTSOCKET_RFCOMM_DLC_CFC) {
2889 pn->flow_control = 0xe0;
2890 pn->credits = RFCOMM_DEFAULT_CREDITS;
2892 pn->flow_control = 0;
2896 hdr->type = RFCOMM_MKMCC_TYPE(0, RFCOMM_MCC_PN);
2897 error = ng_btsocket_rfcomm_send_uih(s,
2898 RFCOMM_MKADDRESS(INITIATOR(s), 0),
2902 ng_btsocket_rfcomm_timeout(pcb);
2903 pcb->state = NG_BTSOCKET_RFCOMM_DLC_CONNECTING;
2904 soisconnecting(pcb->so);
2906 ng_btsocket_rfcomm_pcb_kill(pcb, error);
2908 mtx_unlock(&pcb->pcb_mtx);
2910 /* Nobody is listen()ing on this channel */
2911 error = ng_btsocket_rfcomm_send_command(s,
2912 RFCOMM_FRAME_DM, pn->dlci);
2916 NG_FREE_M(m0); /* XXX ignore response to non-existing dlci */
2919 } /* ng_btsocket_rfcomm_receive_pn */
2922 * Set PN parameters for dlci. Caller must hold pcb->pcb_mtx.
2924 * From Bluetooth spec.
2926 * "... The CL1 - CL4 field is completely redefined. (In TS07.10 this defines
2927 * the convergence layer to use, which is not applicable to RFCOMM. In RFCOMM,
2928 * in Bluetooth versions up to 1.0B, this field was forced to 0).
2930 * In the PN request sent prior to a DLC establishment, this field must contain
2931 * the value 15 (0xF), indicating support of credit based flow control in the
2932 * sender. See Table 5.3 below. If the PN response contains any other value
2933 * than 14 (0xE) in this field, it is inferred that the peer RFCOMM entity is
2934 * not supporting the credit based flow control feature. (This is only possible
2935 * if the peer RFCOMM implementation is only conforming to Bluetooth version
2936 * 1.0B.) If a PN request is sent on an already open DLC, then this field must
2937 * contain the value zero; it is not possible to set initial credits more
2938 * than once per DLC activation. A responding implementation must set this
2939 * field in the PN response to 14 (0xE), if (and only if) the value in the PN
2940 * request was 15..."
2944 ng_btsocket_rfcomm_set_pn(ng_btsocket_rfcomm_pcb_p pcb, u_int8_t cr,
2945 u_int8_t flow_control, u_int8_t credits, u_int16_t mtu)
2947 mtx_assert(&pcb->pcb_mtx, MA_OWNED);
2949 pcb->mtu = le16toh(mtu);
2952 if (flow_control == 0xf0) {
2953 pcb->flags |= NG_BTSOCKET_RFCOMM_DLC_CFC;
2954 pcb->tx_cred = credits;
2956 pcb->flags &= ~NG_BTSOCKET_RFCOMM_DLC_CFC;
2960 if (flow_control == 0xe0) {
2961 pcb->flags |= NG_BTSOCKET_RFCOMM_DLC_CFC;
2962 pcb->tx_cred = credits;
2964 pcb->flags &= ~NG_BTSOCKET_RFCOMM_DLC_CFC;
2969 NG_BTSOCKET_RFCOMM_INFO(
2970 "%s: cr=%d, dlci=%d, state=%d, flags=%#x, mtu=%d, rx_cred=%d, tx_cred=%d\n",
2971 __func__, cr, pcb->dlci, pcb->state, pcb->flags, pcb->mtu,
2972 pcb->rx_cred, pcb->tx_cred);
2973 } /* ng_btsocket_rfcomm_set_pn */
2976 * Send RFCOMM SABM/DISC/UA/DM frames. Caller must hold s->session_mtx
2980 ng_btsocket_rfcomm_send_command(ng_btsocket_rfcomm_session_p s,
2981 u_int8_t type, u_int8_t dlci)
2983 struct rfcomm_cmd_hdr *hdr = NULL;
2984 struct mbuf *m = NULL;
2987 mtx_assert(&s->session_mtx, MA_OWNED);
2989 NG_BTSOCKET_RFCOMM_INFO(
2990 "%s: Sending command type %#x, session state=%d, flags=%#x, mtu=%d, dlci=%d\n",
2991 __func__, type, s->state, s->flags, s->mtu, dlci);
2994 case RFCOMM_FRAME_SABM:
2995 case RFCOMM_FRAME_DISC:
2999 case RFCOMM_FRAME_UA:
3000 case RFCOMM_FRAME_DM:
3005 panic("%s: Invalid frame type=%#x\n", __func__, type);
3010 MGETHDR(m, MB_DONTWAIT, MT_DATA);
3014 m->m_pkthdr.len = m->m_len = sizeof(*hdr);
3016 hdr = mtod(m, struct rfcomm_cmd_hdr *);
3017 hdr->address = RFCOMM_MKADDRESS(cr, dlci);
3018 hdr->control = RFCOMM_MKCONTROL(type, 1);
3019 hdr->length = RFCOMM_MKLEN8(0);
3020 hdr->fcs = ng_btsocket_rfcomm_fcs3((u_int8_t *) hdr);
3022 NG_BT_MBUFQ_ENQUEUE(&s->outq, m);
3025 } /* ng_btsocket_rfcomm_send_command */
3028 * Send RFCOMM UIH frame. Caller must hold s->session_mtx
3032 ng_btsocket_rfcomm_send_uih(ng_btsocket_rfcomm_session_p s, u_int8_t address,
3033 u_int8_t pf, u_int8_t credits, struct mbuf *data)
3035 struct rfcomm_frame_hdr *hdr = NULL;
3036 struct mbuf *m = NULL, *mcrc = NULL;
3039 mtx_assert(&s->session_mtx, MA_OWNED);
3041 MGETHDR(m, MB_DONTWAIT, MT_DATA);
3046 m->m_pkthdr.len = m->m_len = sizeof(*hdr);
3048 MGET(mcrc, MB_DONTWAIT, MT_DATA);
3055 /* Fill UIH frame header */
3056 hdr = mtod(m, struct rfcomm_frame_hdr *);
3057 hdr->address = address;
3058 hdr->control = RFCOMM_MKCONTROL(RFCOMM_FRAME_UIH, pf);
3061 mcrc->m_data[0] = ng_btsocket_rfcomm_fcs2((u_int8_t *) hdr);
3063 /* Put length back */
3064 length = (data != NULL)? data->m_pkthdr.len : 0;
3066 u_int16_t l = htole16(RFCOMM_MKLEN16(length));
3068 bcopy(&l, &hdr->length, sizeof(l));
3072 hdr->length = RFCOMM_MKLEN8(length);
3075 m->m_data[m->m_len] = credits;
3083 m->m_pkthdr.len += length;
3090 NG_BTSOCKET_RFCOMM_INFO(
3091 "%s: Sending UIH state=%d, flags=%#x, address=%d, length=%d, pf=%d, " \
3092 "credits=%d, len=%d\n",
3093 __func__, s->state, s->flags, address, length, pf, credits,
3096 NG_BT_MBUFQ_ENQUEUE(&s->outq, m);
3099 } /* ng_btsocket_rfcomm_send_uih */
3102 * Send MSC request. Caller must hold pcb->pcb_mtx and pcb->session->session_mtx
3106 ng_btsocket_rfcomm_send_msc(ng_btsocket_rfcomm_pcb_p pcb)
3108 struct mbuf *m = NULL;
3109 struct rfcomm_mcc_hdr *hdr = NULL;
3110 struct rfcomm_mcc_msc *msc = NULL;
3112 mtx_assert(&pcb->session->session_mtx, MA_OWNED);
3113 mtx_assert(&pcb->pcb_mtx, MA_OWNED);
3115 MGETHDR(m, MB_DONTWAIT, MT_DATA);
3119 m->m_pkthdr.len = m->m_len = sizeof(*hdr) + sizeof(*msc);
3121 hdr = mtod(m, struct rfcomm_mcc_hdr *);
3122 msc = (struct rfcomm_mcc_msc *)(hdr + 1);
3124 hdr->type = RFCOMM_MKMCC_TYPE(1, RFCOMM_MCC_MSC);
3125 hdr->length = RFCOMM_MKLEN8(sizeof(*msc));
3127 msc->address = RFCOMM_MKADDRESS(1, pcb->dlci);
3128 msc->modem = pcb->lmodem;
3130 NG_BTSOCKET_RFCOMM_INFO(
3131 "%s: Sending MSC dlci=%d, state=%d, flags=%#x, address=%d, modem=%#x\n",
3132 __func__, pcb->dlci, pcb->state, pcb->flags, msc->address,
3135 return (ng_btsocket_rfcomm_send_uih(pcb->session,
3136 RFCOMM_MKADDRESS(INITIATOR(pcb->session), 0), 0, 0, m));
3137 } /* ng_btsocket_rfcomm_send_msc */
3140 * Send PN request. Caller must hold pcb->pcb_mtx and pcb->session->session_mtx
3144 ng_btsocket_rfcomm_send_pn(ng_btsocket_rfcomm_pcb_p pcb)
3146 struct mbuf *m = NULL;
3147 struct rfcomm_mcc_hdr *hdr = NULL;
3148 struct rfcomm_mcc_pn *pn = NULL;
3150 mtx_assert(&pcb->session->session_mtx, MA_OWNED);
3151 mtx_assert(&pcb->pcb_mtx, MA_OWNED);
3153 MGETHDR(m, MB_DONTWAIT, MT_DATA);
3157 m->m_pkthdr.len = m->m_len = sizeof(*hdr) + sizeof(*pn);
3159 hdr = mtod(m, struct rfcomm_mcc_hdr *);
3160 pn = (struct rfcomm_mcc_pn *)(hdr + 1);
3162 hdr->type = RFCOMM_MKMCC_TYPE(1, RFCOMM_MCC_PN);
3163 hdr->length = RFCOMM_MKLEN8(sizeof(*pn));
3165 pn->dlci = pcb->dlci;
3168 * Set default DLCI priority as described in GSM 07.10
3169 * (ETSI TS 101 369) clause 5.6 page 42
3172 pn->priority = (pcb->dlci < 56)? (((pcb->dlci >> 3) << 3) + 7) : 61;
3174 pn->mtu = htole16(pcb->mtu);
3175 pn->max_retrans = 0;
3177 if (pcb->flags & NG_BTSOCKET_RFCOMM_DLC_CFC) {
3178 pn->flow_control = 0xf0;
3179 pn->credits = pcb->rx_cred;
3181 pn->flow_control = 0;
3185 NG_BTSOCKET_RFCOMM_INFO(
3186 "%s: Sending PN dlci=%d, state=%d, flags=%#x, mtu=%d, flow_control=%#x, " \
3187 "credits=%d\n", __func__, pcb->dlci, pcb->state, pcb->flags, pcb->mtu,
3188 pn->flow_control, pn->credits);
3190 return (ng_btsocket_rfcomm_send_uih(pcb->session,
3191 RFCOMM_MKADDRESS(INITIATOR(pcb->session), 0), 0, 0, m));
3192 } /* ng_btsocket_rfcomm_send_pn */
3195 * Calculate and send credits based on available space in receive buffer
3199 ng_btsocket_rfcomm_send_credits(ng_btsocket_rfcomm_pcb_p pcb)
3204 mtx_assert(&pcb->pcb_mtx, MA_OWNED);
3205 mtx_assert(&pcb->session->session_mtx, MA_OWNED);
3207 NG_BTSOCKET_RFCOMM_INFO(
3208 "%s: Sending more credits, dlci=%d, state=%d, flags=%#x, mtu=%d, " \
3209 "space=%ld, tx_cred=%d, rx_cred=%d\n",
3210 __func__, pcb->dlci, pcb->state, pcb->flags, pcb->mtu,
3211 sbspace(&pcb->so->so_rcv), pcb->tx_cred, pcb->rx_cred);
3213 credits = sbspace(&pcb->so->so_rcv) / pcb->mtu;
3215 if (pcb->rx_cred + credits > RFCOMM_MAX_CREDITS)
3216 credits = RFCOMM_MAX_CREDITS - pcb->rx_cred;
3218 error = ng_btsocket_rfcomm_send_uih(
3220 RFCOMM_MKADDRESS(INITIATOR(pcb->session),
3221 pcb->dlci), 1, credits, NULL);
3223 pcb->rx_cred += credits;
3225 NG_BTSOCKET_RFCOMM_INFO(
3226 "%s: Gave remote side %d more credits, dlci=%d, state=%d, flags=%#x, " \
3227 "rx_cred=%d, tx_cred=%d\n", __func__, credits, pcb->dlci, pcb->state,
3228 pcb->flags, pcb->rx_cred, pcb->tx_cred);
3230 NG_BTSOCKET_RFCOMM_ERR(
3231 "%s: Could not send credits, error=%d, dlci=%d, state=%d, flags=%#x, " \
3232 "mtu=%d, space=%ld, tx_cred=%d, rx_cred=%d\n",
3233 __func__, error, pcb->dlci, pcb->state,
3234 pcb->flags, pcb->mtu, sbspace(&pcb->so->so_rcv),
3235 pcb->tx_cred, pcb->rx_cred);
3239 } /* ng_btsocket_rfcomm_send_credits */
3241 /*****************************************************************************
3242 *****************************************************************************
3244 *****************************************************************************
3245 *****************************************************************************/
3248 * Send data from socket send buffer
3249 * Caller must hold pcb->pcb_mtx and pcb->session->session_mtx
3253 ng_btsocket_rfcomm_pcb_send(ng_btsocket_rfcomm_pcb_p pcb, int limit)
3255 struct mbuf *m = NULL;
3256 int sent, length, error;
3258 mtx_assert(&pcb->session->session_mtx, MA_OWNED);
3259 mtx_assert(&pcb->pcb_mtx, MA_OWNED);
3261 if (pcb->flags & NG_BTSOCKET_RFCOMM_DLC_CFC)
3262 limit = min(limit, pcb->tx_cred);
3263 else if (!(pcb->rmodem & RFCOMM_MODEM_FC))
3264 limit = min(limit, RFCOMM_MAX_CREDITS); /* XXX ??? */
3269 NG_BTSOCKET_RFCOMM_INFO(
3270 "%s: Could not send - remote flow control asserted, dlci=%d, flags=%#x, " \
3271 "rmodem=%#x, tx_cred=%d\n",
3272 __func__, pcb->dlci, pcb->flags, pcb->rmodem,
3278 for (error = 0, sent = 0; sent < limit; sent ++) {
3279 length = min(pcb->mtu, pcb->so->so_snd.sb_cc);
3283 /* Get the chunk from the socket's send buffer */
3284 m = ng_btsocket_rfcomm_prepare_packet(&pcb->so->so_snd, length);
3290 sbdrop(&pcb->so->so_snd, length);
3292 error = ng_btsocket_rfcomm_send_uih(pcb->session,
3293 RFCOMM_MKADDRESS(INITIATOR(pcb->session),
3294 pcb->dlci), 0, 0, m);
3299 if (pcb->flags & NG_BTSOCKET_RFCOMM_DLC_CFC)
3300 pcb->tx_cred -= sent;
3302 if (error == 0 && sent > 0) {
3303 pcb->flags &= ~NG_BTSOCKET_RFCOMM_DLC_SENDING;
3308 } /* ng_btsocket_rfcomm_pcb_send */
3311 * Unlink and disconnect DLC. If ng_btsocket_rfcomm_pcb_kill() returns
3312 * non zero value than socket has no reference and has to be detached.
3313 * Caller must hold pcb->pcb_mtx and pcb->session->session_mtx
3317 ng_btsocket_rfcomm_pcb_kill(ng_btsocket_rfcomm_pcb_p pcb, int error)
3319 ng_btsocket_rfcomm_session_p s = pcb->session;
3321 NG_BTSOCKET_RFCOMM_INFO(
3322 "%s: Killing DLC, so=%p, dlci=%d, state=%d, flags=%#x, error=%d\n",
3323 __func__, pcb->so, pcb->dlci, pcb->state, pcb->flags, error);
3325 if (pcb->session == NULL)
3326 panic("%s: DLC without session, pcb=%p, state=%d, flags=%#x\n",
3327 __func__, pcb, pcb->state, pcb->flags);
3329 mtx_assert(&pcb->session->session_mtx, MA_OWNED);
3330 mtx_assert(&pcb->pcb_mtx, MA_OWNED);
3332 if (pcb->flags & NG_BTSOCKET_RFCOMM_DLC_TIMO)
3333 ng_btsocket_rfcomm_untimeout(pcb);
3335 /* Detach DLC from the session. Does not matter which state DLC in */
3336 LIST_REMOVE(pcb, session_next);
3337 pcb->session = NULL;
3339 /* Change DLC state and wakeup all sleepers */
3340 pcb->state = NG_BTSOCKET_RFCOMM_DLC_CLOSED;
3341 pcb->so->so_error = error;
3342 soisdisconnected(pcb->so);
3343 wakeup(&pcb->state);
3345 /* Check if we have any DLCs left on the session */
3346 if (LIST_EMPTY(&s->dlcs) && INITIATOR(s)) {
3347 NG_BTSOCKET_RFCOMM_INFO(
3348 "%s: Disconnecting session, state=%d, flags=%#x, mtu=%d\n",
3349 __func__, s->state, s->flags, s->mtu);
3352 case NG_BTSOCKET_RFCOMM_SESSION_CLOSED:
3353 case NG_BTSOCKET_RFCOMM_SESSION_DISCONNECTING:
3355 * Do not have to do anything here. We can get here
3356 * when L2CAP connection was terminated or we have
3357 * received DISC on multiplexor channel
3361 case NG_BTSOCKET_RFCOMM_SESSION_OPEN:
3362 /* Send DISC on multiplexor channel */
3363 error = ng_btsocket_rfcomm_send_command(s,
3364 RFCOMM_FRAME_DISC, 0);
3366 s->state = NG_BTSOCKET_RFCOMM_SESSION_DISCONNECTING;
3371 case NG_BTSOCKET_RFCOMM_SESSION_CONNECTING:
3372 case NG_BTSOCKET_RFCOMM_SESSION_CONNECTED:
3373 s->state = NG_BTSOCKET_RFCOMM_SESSION_CLOSED;
3376 /* case NG_BTSOCKET_RFCOMM_SESSION_LISTENING: */
3378 panic("%s: Invalid session state=%d, flags=%#x\n",
3379 __func__, s->state, s->flags);
3383 ng_btsocket_rfcomm_task_wakeup();
3385 } /* ng_btsocket_rfcomm_pcb_kill */
3388 * Look for given dlci for given RFCOMM session. Caller must hold s->session_mtx
3391 static ng_btsocket_rfcomm_pcb_p
3392 ng_btsocket_rfcomm_pcb_by_dlci(ng_btsocket_rfcomm_session_p s, int dlci)
3394 ng_btsocket_rfcomm_pcb_p pcb = NULL;
3396 mtx_assert(&s->session_mtx, MA_OWNED);
3398 LIST_FOREACH(pcb, &s->dlcs, session_next)
3399 if (pcb->dlci == dlci)
3403 } /* ng_btsocket_rfcomm_pcb_by_dlci */
3406 * Look for socket that listens on given src address and given channel
3409 static ng_btsocket_rfcomm_pcb_p
3410 ng_btsocket_rfcomm_pcb_listener(bdaddr_p src, int channel)
3412 ng_btsocket_rfcomm_pcb_p pcb = NULL, pcb1 = NULL;
3414 mtx_lock(&ng_btsocket_rfcomm_sockets_mtx);
3416 LIST_FOREACH(pcb, &ng_btsocket_rfcomm_sockets, next) {
3417 if (pcb->channel != channel ||
3418 !(pcb->so->so_options & SO_ACCEPTCONN))
3421 if (bcmp(&pcb->src, src, sizeof(*src)) == 0)
3424 if (bcmp(&pcb->src, NG_HCI_BDADDR_ANY, sizeof(bdaddr_t)) == 0)
3428 mtx_unlock(&ng_btsocket_rfcomm_sockets_mtx);
3430 return ((pcb != NULL)? pcb : pcb1);
3431 } /* ng_btsocket_rfcomm_pcb_listener */
3433 /*****************************************************************************
3434 *****************************************************************************
3436 *****************************************************************************
3437 *****************************************************************************/
3440 * Set timeout. Caller MUST hold pcb_mtx
3444 ng_btsocket_rfcomm_timeout(ng_btsocket_rfcomm_pcb_p pcb)
3446 mtx_assert(&pcb->pcb_mtx, MA_OWNED);
3448 if (!(pcb->flags & NG_BTSOCKET_RFCOMM_DLC_TIMO)) {
3449 pcb->flags |= NG_BTSOCKET_RFCOMM_DLC_TIMO;
3450 pcb->flags &= ~NG_BTSOCKET_RFCOMM_DLC_TIMEDOUT;
3451 pcb->timo = timeout(ng_btsocket_rfcomm_process_timeout, pcb,
3452 ng_btsocket_rfcomm_timo * hz);
3454 panic("%s: Duplicated socket timeout?!\n", __func__);
3455 } /* ng_btsocket_rfcomm_timeout */
3458 * Unset pcb timeout. Caller MUST hold pcb_mtx
3462 ng_btsocket_rfcomm_untimeout(ng_btsocket_rfcomm_pcb_p pcb)
3464 mtx_assert(&pcb->pcb_mtx, MA_OWNED);
3466 if (pcb->flags & NG_BTSOCKET_RFCOMM_DLC_TIMO) {
3467 untimeout(ng_btsocket_rfcomm_process_timeout, pcb, pcb->timo);
3468 pcb->flags &= ~NG_BTSOCKET_RFCOMM_DLC_TIMO;
3469 pcb->flags &= ~NG_BTSOCKET_RFCOMM_DLC_TIMEDOUT;
3471 panic("%s: No socket timeout?!\n", __func__);
3472 } /* ng_btsocket_rfcomm_timeout */
3475 * Process pcb timeout
3479 ng_btsocket_rfcomm_process_timeout(void *xpcb)
3481 ng_btsocket_rfcomm_pcb_p pcb = (ng_btsocket_rfcomm_pcb_p) xpcb;
3483 mtx_lock(&pcb->pcb_mtx);
3485 NG_BTSOCKET_RFCOMM_INFO(
3486 "%s: Timeout, so=%p, dlci=%d, state=%d, flags=%#x\n",
3487 __func__, pcb->so, pcb->dlci, pcb->state, pcb->flags);
3489 pcb->flags &= ~NG_BTSOCKET_RFCOMM_DLC_TIMO;
3490 pcb->flags |= NG_BTSOCKET_RFCOMM_DLC_TIMEDOUT;
3492 switch (pcb->state) {
3493 case NG_BTSOCKET_RFCOMM_DLC_CONFIGURING:
3494 case NG_BTSOCKET_RFCOMM_DLC_CONNECTING:
3495 pcb->state = NG_BTSOCKET_RFCOMM_DLC_DISCONNECTING;
3498 case NG_BTSOCKET_RFCOMM_DLC_W4_CONNECT:
3499 case NG_BTSOCKET_RFCOMM_DLC_DISCONNECTING:
3504 "%s: DLC timeout in invalid state, dlci=%d, state=%d, flags=%#x\n",
3505 __func__, pcb->dlci, pcb->state, pcb->flags);
3509 ng_btsocket_rfcomm_task_wakeup();
3511 mtx_unlock(&pcb->pcb_mtx);
3512 } /* ng_btsocket_rfcomm_process_timeout */
3515 * Get up to length bytes from the socket buffer
3518 static struct mbuf *
3519 ng_btsocket_rfcomm_prepare_packet(struct sockbuf *sb, int length)
3521 struct mbuf *top = NULL, *m = NULL, *n = NULL, *nextpkt = NULL;
3522 int mlen, noff, len;
3524 MGETHDR(top, MB_DONTWAIT, MT_DATA);
3528 top->m_pkthdr.len = length;
3534 nextpkt = n->m_nextpkt;
3537 while (length > 0 && n != NULL) {
3538 len = min(mlen - m->m_len, n->m_len - noff);
3542 bcopy(mtod(n, caddr_t)+noff, mtod(m, caddr_t)+m->m_len, len);
3547 if (length > 0 && m->m_len == mlen) {
3548 MGET(m->m_next, MB_DONTWAIT, MT_DATA);
3549 if (m->m_next == NULL) {
3559 if (noff == n->m_len) {
3566 nextpkt = (n != NULL)? n->m_nextpkt : NULL;
3571 panic("%s: length=%d\n", __func__, length);
3572 if (length > 0 && n == NULL)
3573 panic("%s: bogus length=%d, n=%p\n", __func__, length, n);
3576 } /* ng_btsocket_rfcomm_prepare_packet */