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 $
34 #include <sys/param.h>
35 #include <sys/systm.h>
36 #include <sys/bitstring.h>
37 #include <sys/domain.h>
38 #include <sys/endian.h>
39 #include <sys/errno.h>
40 #include <sys/filedesc.h>
41 #include <sys/ioccom.h>
42 #include <sys/kernel.h>
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 <netgraph/ng_message.h>
56 #include <netgraph/netgraph.h>
57 #include <netgraph/bluetooth/include/ng_bluetooth.h>
58 #include <netgraph/bluetooth/include/ng_hci.h>
59 #include <netgraph/bluetooth/include/ng_l2cap.h>
60 #include <netgraph/bluetooth/include/ng_btsocket.h>
61 #include <netgraph/bluetooth/include/ng_btsocket_l2cap.h>
62 #include <netgraph/bluetooth/include/ng_btsocket_rfcomm.h>
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 && \
75 ppsratecheck(&ng_btsocket_rfcomm_lasttime, &ng_btsocket_rfcomm_curpps, 1)) \
78 #define NG_BTSOCKET_RFCOMM_WARN \
79 if (ng_btsocket_rfcomm_debug_level >= NG_BTSOCKET_WARN_LEVEL && \
80 ppsratecheck(&ng_btsocket_rfcomm_lasttime, &ng_btsocket_rfcomm_curpps, 1)) \
83 #define NG_BTSOCKET_RFCOMM_ERR \
84 if (ng_btsocket_rfcomm_debug_level >= NG_BTSOCKET_ERR_LEVEL && \
85 ppsratecheck(&ng_btsocket_rfcomm_lasttime, &ng_btsocket_rfcomm_curpps, 1)) \
88 #define NG_BTSOCKET_RFCOMM_ALERT \
89 if (ng_btsocket_rfcomm_debug_level >= NG_BTSOCKET_ALERT_LEVEL && \
90 ppsratecheck(&ng_btsocket_rfcomm_lasttime, &ng_btsocket_rfcomm_curpps, 1)) \
95 /* Local prototypes */
96 static void ng_btsocket_rfcomm_upcall
97 (struct socket *so, void *arg, int waitflag);
98 static void ng_btsocket_rfcomm_sessions_task
99 (void *ctx, int pending);
100 static void ng_btsocket_rfcomm_session_task
101 (ng_btsocket_rfcomm_session_p s);
102 #define ng_btsocket_rfcomm_task_wakeup() \
103 taskqueue_enqueue(taskqueue_swi_giant, &ng_btsocket_rfcomm_task)
105 static ng_btsocket_rfcomm_pcb_p ng_btsocket_rfcomm_connect_ind
106 (ng_btsocket_rfcomm_session_p s, int channel);
107 static void ng_btsocket_rfcomm_connect_cfm
108 (ng_btsocket_rfcomm_session_p s);
110 static int ng_btsocket_rfcomm_session_create
111 (ng_btsocket_rfcomm_session_p *sp, struct socket *l2so,
112 bdaddr_p src, bdaddr_p dst, struct thread *td);
113 static int ng_btsocket_rfcomm_session_accept
114 (ng_btsocket_rfcomm_session_p s0);
115 static int ng_btsocket_rfcomm_session_connect
116 (ng_btsocket_rfcomm_session_p s);
117 static int ng_btsocket_rfcomm_session_receive
118 (ng_btsocket_rfcomm_session_p s);
119 static int ng_btsocket_rfcomm_session_send
120 (ng_btsocket_rfcomm_session_p s);
121 static void ng_btsocket_rfcomm_session_clean
122 (ng_btsocket_rfcomm_session_p s);
123 static void ng_btsocket_rfcomm_session_process_pcb
124 (ng_btsocket_rfcomm_session_p s);
125 static ng_btsocket_rfcomm_session_p ng_btsocket_rfcomm_session_by_addr
126 (bdaddr_p src, bdaddr_p dst);
128 static int ng_btsocket_rfcomm_receive_frame
129 (ng_btsocket_rfcomm_session_p s, struct mbuf *m0);
130 static int ng_btsocket_rfcomm_receive_sabm
131 (ng_btsocket_rfcomm_session_p s, int dlci);
132 static int ng_btsocket_rfcomm_receive_disc
133 (ng_btsocket_rfcomm_session_p s, int dlci);
134 static int ng_btsocket_rfcomm_receive_ua
135 (ng_btsocket_rfcomm_session_p s, int dlci);
136 static int ng_btsocket_rfcomm_receive_dm
137 (ng_btsocket_rfcomm_session_p s, int dlci);
138 static int ng_btsocket_rfcomm_receive_uih
139 (ng_btsocket_rfcomm_session_p s, int dlci, int pf, struct mbuf *m0);
140 static int ng_btsocket_rfcomm_receive_mcc
141 (ng_btsocket_rfcomm_session_p s, struct mbuf *m0);
142 static int ng_btsocket_rfcomm_receive_test
143 (ng_btsocket_rfcomm_session_p s, struct mbuf *m0);
144 static int ng_btsocket_rfcomm_receive_fc
145 (ng_btsocket_rfcomm_session_p s, struct mbuf *m0);
146 static int ng_btsocket_rfcomm_receive_msc
147 (ng_btsocket_rfcomm_session_p s, struct mbuf *m0);
148 static int ng_btsocket_rfcomm_receive_rpn
149 (ng_btsocket_rfcomm_session_p s, struct mbuf *m0);
150 static int ng_btsocket_rfcomm_receive_rls
151 (ng_btsocket_rfcomm_session_p s, struct mbuf *m0);
152 static int ng_btsocket_rfcomm_receive_pn
153 (ng_btsocket_rfcomm_session_p s, struct mbuf *m0);
154 static void ng_btsocket_rfcomm_set_pn
155 (ng_btsocket_rfcomm_pcb_p pcb, u_int8_t cr, u_int8_t flow_control,
156 u_int8_t credits, u_int16_t mtu);
158 static int ng_btsocket_rfcomm_send_command
159 (ng_btsocket_rfcomm_session_p s, u_int8_t type, u_int8_t dlci);
160 static int ng_btsocket_rfcomm_send_uih
161 (ng_btsocket_rfcomm_session_p s, u_int8_t address, u_int8_t pf,
162 u_int8_t credits, struct mbuf *data);
163 static int ng_btsocket_rfcomm_send_msc
164 (ng_btsocket_rfcomm_pcb_p pcb);
165 static int ng_btsocket_rfcomm_send_pn
166 (ng_btsocket_rfcomm_pcb_p pcb);
167 static int ng_btsocket_rfcomm_send_credits
168 (ng_btsocket_rfcomm_pcb_p pcb);
170 static int ng_btsocket_rfcomm_pcb_send
171 (ng_btsocket_rfcomm_pcb_p pcb, int limit);
172 static void ng_btsocket_rfcomm_pcb_kill
173 (ng_btsocket_rfcomm_pcb_p pcb, int error);
174 static ng_btsocket_rfcomm_pcb_p ng_btsocket_rfcomm_pcb_by_dlci
175 (ng_btsocket_rfcomm_session_p s, int dlci);
176 static ng_btsocket_rfcomm_pcb_p ng_btsocket_rfcomm_pcb_listener
177 (bdaddr_p src, int channel);
179 static void ng_btsocket_rfcomm_timeout
180 (ng_btsocket_rfcomm_pcb_p pcb);
181 static void ng_btsocket_rfcomm_untimeout
182 (ng_btsocket_rfcomm_pcb_p pcb);
183 static void ng_btsocket_rfcomm_process_timeout
186 static struct mbuf * ng_btsocket_rfcomm_prepare_packet
187 (struct sockbuf *sb, int length);
190 extern int ifqmaxlen;
191 static u_int32_t ng_btsocket_rfcomm_debug_level;
192 static u_int32_t ng_btsocket_rfcomm_timo;
193 struct task ng_btsocket_rfcomm_task;
194 static LIST_HEAD(, ng_btsocket_rfcomm_session) ng_btsocket_rfcomm_sessions;
195 static struct mtx ng_btsocket_rfcomm_sessions_mtx;
196 static LIST_HEAD(, ng_btsocket_rfcomm_pcb) ng_btsocket_rfcomm_sockets;
197 static struct mtx ng_btsocket_rfcomm_sockets_mtx;
198 static struct timeval ng_btsocket_rfcomm_lasttime;
199 static int ng_btsocket_rfcomm_curpps;
202 SYSCTL_DECL(_net_bluetooth_rfcomm_sockets);
203 SYSCTL_NODE(_net_bluetooth_rfcomm_sockets, OID_AUTO, stream, CTLFLAG_RW,
204 0, "Bluetooth STREAM RFCOMM sockets family");
205 SYSCTL_INT(_net_bluetooth_rfcomm_sockets_stream, OID_AUTO, debug_level,
207 &ng_btsocket_rfcomm_debug_level, NG_BTSOCKET_INFO_LEVEL,
208 "Bluetooth STREAM RFCOMM sockets debug level");
209 SYSCTL_INT(_net_bluetooth_rfcomm_sockets_stream, OID_AUTO, timeout,
211 &ng_btsocket_rfcomm_timo, 60,
212 "Bluetooth STREAM RFCOMM sockets timeout");
214 /*****************************************************************************
215 *****************************************************************************
217 *****************************************************************************
218 *****************************************************************************/
220 static u_int8_t ng_btsocket_rfcomm_crc_table[256] = {
221 0x00, 0x91, 0xe3, 0x72, 0x07, 0x96, 0xe4, 0x75,
222 0x0e, 0x9f, 0xed, 0x7c, 0x09, 0x98, 0xea, 0x7b,
223 0x1c, 0x8d, 0xff, 0x6e, 0x1b, 0x8a, 0xf8, 0x69,
224 0x12, 0x83, 0xf1, 0x60, 0x15, 0x84, 0xf6, 0x67,
226 0x38, 0xa9, 0xdb, 0x4a, 0x3f, 0xae, 0xdc, 0x4d,
227 0x36, 0xa7, 0xd5, 0x44, 0x31, 0xa0, 0xd2, 0x43,
228 0x24, 0xb5, 0xc7, 0x56, 0x23, 0xb2, 0xc0, 0x51,
229 0x2a, 0xbb, 0xc9, 0x58, 0x2d, 0xbc, 0xce, 0x5f,
231 0x70, 0xe1, 0x93, 0x02, 0x77, 0xe6, 0x94, 0x05,
232 0x7e, 0xef, 0x9d, 0x0c, 0x79, 0xe8, 0x9a, 0x0b,
233 0x6c, 0xfd, 0x8f, 0x1e, 0x6b, 0xfa, 0x88, 0x19,
234 0x62, 0xf3, 0x81, 0x10, 0x65, 0xf4, 0x86, 0x17,
236 0x48, 0xd9, 0xab, 0x3a, 0x4f, 0xde, 0xac, 0x3d,
237 0x46, 0xd7, 0xa5, 0x34, 0x41, 0xd0, 0xa2, 0x33,
238 0x54, 0xc5, 0xb7, 0x26, 0x53, 0xc2, 0xb0, 0x21,
239 0x5a, 0xcb, 0xb9, 0x28, 0x5d, 0xcc, 0xbe, 0x2f,
241 0xe0, 0x71, 0x03, 0x92, 0xe7, 0x76, 0x04, 0x95,
242 0xee, 0x7f, 0x0d, 0x9c, 0xe9, 0x78, 0x0a, 0x9b,
243 0xfc, 0x6d, 0x1f, 0x8e, 0xfb, 0x6a, 0x18, 0x89,
244 0xf2, 0x63, 0x11, 0x80, 0xf5, 0x64, 0x16, 0x87,
246 0xd8, 0x49, 0x3b, 0xaa, 0xdf, 0x4e, 0x3c, 0xad,
247 0xd6, 0x47, 0x35, 0xa4, 0xd1, 0x40, 0x32, 0xa3,
248 0xc4, 0x55, 0x27, 0xb6, 0xc3, 0x52, 0x20, 0xb1,
249 0xca, 0x5b, 0x29, 0xb8, 0xcd, 0x5c, 0x2e, 0xbf,
251 0x90, 0x01, 0x73, 0xe2, 0x97, 0x06, 0x74, 0xe5,
252 0x9e, 0x0f, 0x7d, 0xec, 0x99, 0x08, 0x7a, 0xeb,
253 0x8c, 0x1d, 0x6f, 0xfe, 0x8b, 0x1a, 0x68, 0xf9,
254 0x82, 0x13, 0x61, 0xf0, 0x85, 0x14, 0x66, 0xf7,
256 0xa8, 0x39, 0x4b, 0xda, 0xaf, 0x3e, 0x4c, 0xdd,
257 0xa6, 0x37, 0x45, 0xd4, 0xa1, 0x30, 0x42, 0xd3,
258 0xb4, 0x25, 0x57, 0xc6, 0xb3, 0x22, 0x50, 0xc1,
259 0xba, 0x2b, 0x59, 0xc8, 0xbd, 0x2c, 0x5e, 0xcf
264 ng_btsocket_rfcomm_crc(u_int8_t *data, int length)
269 crc = ng_btsocket_rfcomm_crc_table[crc ^ *data++];
272 } /* ng_btsocket_rfcomm_crc */
276 ng_btsocket_rfcomm_fcs2(u_int8_t *data)
278 return (0xff - ng_btsocket_rfcomm_crc(data, 2));
279 } /* ng_btsocket_rfcomm_fcs2 */
283 ng_btsocket_rfcomm_fcs3(u_int8_t *data)
285 return (0xff - ng_btsocket_rfcomm_crc(data, 3));
286 } /* ng_btsocket_rfcomm_fcs3 */
291 * From Bluetooth spec
293 * "... In 07.10, the frame check sequence (FCS) is calculated on different
294 * sets of fields for different frame types. These are the fields that the
295 * FCS are calculated on:
297 * For SABM, DISC, UA, DM frames: on Address, Control and length field.
298 * For UIH frames: on Address and Control field.
300 * (This is stated here for clarification, and to set the standard for RFCOMM;
301 * the fields included in FCS calculation have actually changed in version
302 * 7.0.0 of TS 07.10, but RFCOMM will not change the FCS calculation scheme
303 * from the one above.) ..."
307 ng_btsocket_rfcomm_check_fcs(u_int8_t *data, int type, u_int8_t fcs)
309 if (type != RFCOMM_FRAME_UIH)
310 return (ng_btsocket_rfcomm_fcs3(data) != fcs);
312 return (ng_btsocket_rfcomm_fcs2(data) != fcs);
313 } /* ng_btsocket_rfcomm_check_fcs */
315 /*****************************************************************************
316 *****************************************************************************
318 *****************************************************************************
319 *****************************************************************************/
322 * Initialize everything
326 ng_btsocket_rfcomm_init(void)
328 ng_btsocket_rfcomm_debug_level = NG_BTSOCKET_WARN_LEVEL;
329 ng_btsocket_rfcomm_timo = 60;
332 TASK_INIT(&ng_btsocket_rfcomm_task, 0,
333 ng_btsocket_rfcomm_sessions_task, NULL);
335 /* RFCOMM sessions list */
336 LIST_INIT(&ng_btsocket_rfcomm_sessions);
337 mtx_init(&ng_btsocket_rfcomm_sessions_mtx,
338 "btsocks_rfcomm_sessions_mtx", NULL, MTX_DEF);
340 /* RFCOMM sockets list */
341 LIST_INIT(&ng_btsocket_rfcomm_sockets);
342 mtx_init(&ng_btsocket_rfcomm_sockets_mtx,
343 "btsocks_rfcomm_sockets_mtx", NULL, MTX_DEF);
344 } /* ng_btsocket_rfcomm_init */
347 * Abort connection on socket
351 ng_btsocket_rfcomm_abort(struct socket *so)
354 so->so_error = ECONNABORTED;
355 (void)ng_btsocket_rfcomm_disconnect(so);
356 } /* ng_btsocket_rfcomm_abort */
359 ng_btsocket_rfcomm_close(struct socket *so)
362 (void)ng_btsocket_rfcomm_disconnect(so);
363 } /* ng_btsocket_rfcomm_close */
366 * Accept connection on socket. Nothing to do here, socket must be connected
367 * and ready, so just return peer address and be done with it.
371 ng_btsocket_rfcomm_accept(struct socket *so, struct sockaddr **nam)
373 return (ng_btsocket_rfcomm_peeraddr(so, nam));
374 } /* ng_btsocket_rfcomm_accept */
377 * Create and attach new socket
381 ng_btsocket_rfcomm_attach(struct socket *so, int proto, struct thread *td)
383 ng_btsocket_rfcomm_pcb_p pcb = so2rfcomm_pcb(so);
386 /* Check socket and protocol */
387 if (so->so_type != SOCK_STREAM)
388 return (ESOCKTNOSUPPORT);
390 #if 0 /* XXX sonewconn() calls "pru_attach" with proto == 0 */
392 if (proto != BLUETOOTH_PROTO_RFCOMM)
393 return (EPROTONOSUPPORT);
399 /* Reserve send and receive space if it is not reserved yet */
400 if ((so->so_snd.sb_hiwat == 0) || (so->so_rcv.sb_hiwat == 0)) {
401 error = soreserve(so, NG_BTSOCKET_RFCOMM_SENDSPACE,
402 NG_BTSOCKET_RFCOMM_RECVSPACE);
407 /* Allocate the PCB */
408 MALLOC(pcb, ng_btsocket_rfcomm_pcb_p, sizeof(*pcb),
409 M_NETGRAPH_BTSOCKET_RFCOMM, M_NOWAIT | M_ZERO);
413 /* Link the PCB and the socket */
414 so->so_pcb = (caddr_t) pcb;
418 pcb->state = NG_BTSOCKET_RFCOMM_DLC_CLOSED;
419 pcb->flags = NG_BTSOCKET_RFCOMM_DLC_CFC;
422 pcb->rmodem = (RFCOMM_MODEM_RTC | RFCOMM_MODEM_RTR | RFCOMM_MODEM_DV);
424 pcb->mtu = RFCOMM_DEFAULT_MTU;
426 pcb->rx_cred = RFCOMM_DEFAULT_CREDITS;
428 mtx_init(&pcb->pcb_mtx, "btsocks_rfcomm_pcb_mtx", NULL, MTX_DEF);
429 callout_handle_init(&pcb->timo);
431 /* Add the PCB to the list */
432 mtx_lock(&ng_btsocket_rfcomm_sockets_mtx);
433 LIST_INSERT_HEAD(&ng_btsocket_rfcomm_sockets, pcb, next);
434 mtx_unlock(&ng_btsocket_rfcomm_sockets_mtx);
437 } /* ng_btsocket_rfcomm_attach */
444 ng_btsocket_rfcomm_bind(struct socket *so, struct sockaddr *nam,
447 ng_btsocket_rfcomm_pcb_t *pcb = so2rfcomm_pcb(so), *pcb1;
448 struct sockaddr_rfcomm *sa = (struct sockaddr_rfcomm *) nam;
456 if (sa->rfcomm_family != AF_BLUETOOTH)
457 return (EAFNOSUPPORT);
458 if (sa->rfcomm_len != sizeof(*sa))
460 if (sa->rfcomm_channel > 30)
463 mtx_lock(&pcb->pcb_mtx);
465 if (sa->rfcomm_channel != 0) {
466 mtx_lock(&ng_btsocket_rfcomm_sockets_mtx);
468 LIST_FOREACH(pcb1, &ng_btsocket_rfcomm_sockets, next) {
469 if (pcb1->channel == sa->rfcomm_channel &&
470 bcmp(&pcb1->src, &sa->rfcomm_bdaddr,
471 sizeof(pcb1->src)) == 0) {
472 mtx_unlock(&ng_btsocket_rfcomm_sockets_mtx);
473 mtx_unlock(&pcb->pcb_mtx);
479 mtx_unlock(&ng_btsocket_rfcomm_sockets_mtx);
482 bcopy(&sa->rfcomm_bdaddr, &pcb->src, sizeof(pcb->src));
483 pcb->channel = sa->rfcomm_channel;
485 mtx_unlock(&pcb->pcb_mtx);
488 } /* ng_btsocket_rfcomm_bind */
495 ng_btsocket_rfcomm_connect(struct socket *so, struct sockaddr *nam,
498 ng_btsocket_rfcomm_pcb_t *pcb = so2rfcomm_pcb(so);
499 struct sockaddr_rfcomm *sa = (struct sockaddr_rfcomm *) nam;
500 ng_btsocket_rfcomm_session_t *s = NULL;
501 struct socket *l2so = NULL;
510 if (sa->rfcomm_family != AF_BLUETOOTH)
511 return (EAFNOSUPPORT);
512 if (sa->rfcomm_len != sizeof(*sa))
514 if (sa->rfcomm_channel > 30)
516 if (sa->rfcomm_channel == 0 ||
517 bcmp(&sa->rfcomm_bdaddr, NG_HCI_BDADDR_ANY, sizeof(bdaddr_t)) == 0)
518 return (EDESTADDRREQ);
521 * Note that we will not check for errors in socreate() because
522 * if we failed to create L2CAP socket at this point we still
523 * might have already open session.
526 error = socreate(PF_BLUETOOTH, &l2so, SOCK_SEQPACKET,
527 BLUETOOTH_PROTO_L2CAP, td->td_ucred, td);
530 * Look for session between "pcb->src" and "sa->rfcomm_bdaddr" (dst)
533 mtx_lock(&ng_btsocket_rfcomm_sessions_mtx);
535 s = ng_btsocket_rfcomm_session_by_addr(&pcb->src, &sa->rfcomm_bdaddr);
538 * We need to create new RFCOMM session. Check if we have L2CAP
539 * socket. If l2so == NULL then error has the error code from
544 mtx_unlock(&ng_btsocket_rfcomm_sessions_mtx);
548 error = ng_btsocket_rfcomm_session_create(&s, l2so,
549 &pcb->src, &sa->rfcomm_bdaddr, td);
551 mtx_unlock(&ng_btsocket_rfcomm_sessions_mtx);
556 } else if (l2so != NULL)
557 soclose(l2so); /* we don't need new L2CAP socket */
560 * Check if we already have the same DLCI the the same session
563 mtx_lock(&s->session_mtx);
564 mtx_lock(&pcb->pcb_mtx);
566 dlci = RFCOMM_MKDLCI(!INITIATOR(s), sa->rfcomm_channel);
568 if (ng_btsocket_rfcomm_pcb_by_dlci(s, dlci) != NULL) {
569 mtx_unlock(&pcb->pcb_mtx);
570 mtx_unlock(&s->session_mtx);
571 mtx_unlock(&ng_btsocket_rfcomm_sessions_mtx);
577 * Check session state and if its not acceptable then refuse connection
581 case NG_BTSOCKET_RFCOMM_SESSION_CONNECTING:
582 case NG_BTSOCKET_RFCOMM_SESSION_CONNECTED:
583 case NG_BTSOCKET_RFCOMM_SESSION_OPEN:
585 * Update destination address and channel and attach
589 bcopy(&sa->rfcomm_bdaddr, &pcb->dst, sizeof(pcb->dst));
590 pcb->channel = sa->rfcomm_channel;
593 LIST_INSERT_HEAD(&s->dlcs, pcb, session_next);
596 ng_btsocket_rfcomm_timeout(pcb);
597 soisconnecting(pcb->so);
599 if (s->state == NG_BTSOCKET_RFCOMM_SESSION_OPEN) {
601 bcopy(&so2l2cap_pcb(s->l2so)->src, &pcb->src,
604 pcb->state = NG_BTSOCKET_RFCOMM_DLC_CONFIGURING;
606 error = ng_btsocket_rfcomm_send_pn(pcb);
608 error = ng_btsocket_rfcomm_task_wakeup();
610 pcb->state = NG_BTSOCKET_RFCOMM_DLC_W4_CONNECT;
618 mtx_unlock(&pcb->pcb_mtx);
619 mtx_unlock(&s->session_mtx);
620 mtx_unlock(&ng_btsocket_rfcomm_sessions_mtx);
623 } /* ng_btsocket_rfcomm_connect */
626 * Process ioctl's calls on socket.
627 * XXX FIXME this should provide interface to the RFCOMM multiplexor channel
631 ng_btsocket_rfcomm_control(struct socket *so, u_long cmd, caddr_t data,
632 struct ifnet *ifp, struct thread *td)
635 } /* ng_btsocket_rfcomm_control */
638 * Process getsockopt/setsockopt system calls
642 ng_btsocket_rfcomm_ctloutput(struct socket *so, struct sockopt *sopt)
644 ng_btsocket_rfcomm_pcb_p pcb = so2rfcomm_pcb(so);
645 struct ng_btsocket_rfcomm_fc_info fcinfo;
650 if (sopt->sopt_level != SOL_RFCOMM)
653 mtx_lock(&pcb->pcb_mtx);
655 switch (sopt->sopt_dir) {
657 switch (sopt->sopt_name) {
659 error = sooptcopyout(sopt, &pcb->mtu, sizeof(pcb->mtu));
662 case SO_RFCOMM_FC_INFO:
663 fcinfo.lmodem = pcb->lmodem;
664 fcinfo.rmodem = pcb->rmodem;
665 fcinfo.tx_cred = pcb->tx_cred;
666 fcinfo.rx_cred = pcb->rx_cred;
667 fcinfo.cfc = (pcb->flags & NG_BTSOCKET_RFCOMM_DLC_CFC)?
671 error = sooptcopyout(sopt, &fcinfo, sizeof(fcinfo));
681 switch (sopt->sopt_name) {
693 mtx_unlock(&pcb->pcb_mtx);
696 } /* ng_btsocket_rfcomm_ctloutput */
699 * Detach and destroy socket
703 ng_btsocket_rfcomm_detach(struct socket *so)
705 ng_btsocket_rfcomm_pcb_p pcb = so2rfcomm_pcb(so);
707 KASSERT(pcb != NULL, ("ng_btsocket_rfcomm_detach: pcb == NULL"));
709 mtx_lock(&pcb->pcb_mtx);
711 switch (pcb->state) {
712 case NG_BTSOCKET_RFCOMM_DLC_W4_CONNECT:
713 case NG_BTSOCKET_RFCOMM_DLC_CONFIGURING:
714 case NG_BTSOCKET_RFCOMM_DLC_CONNECTING:
715 case NG_BTSOCKET_RFCOMM_DLC_CONNECTED:
716 /* XXX What to do with pending request? */
717 if (pcb->flags & NG_BTSOCKET_RFCOMM_DLC_TIMO)
718 ng_btsocket_rfcomm_untimeout(pcb);
720 if (pcb->state == NG_BTSOCKET_RFCOMM_DLC_W4_CONNECT)
721 pcb->flags |= NG_BTSOCKET_RFCOMM_DLC_DETACHED;
723 pcb->state = NG_BTSOCKET_RFCOMM_DLC_DISCONNECTING;
725 ng_btsocket_rfcomm_task_wakeup();
728 case NG_BTSOCKET_RFCOMM_DLC_DISCONNECTING:
729 ng_btsocket_rfcomm_task_wakeup();
733 while (pcb->state != NG_BTSOCKET_RFCOMM_DLC_CLOSED)
734 msleep(&pcb->state, &pcb->pcb_mtx, PZERO, "rf_det", 0);
736 if (pcb->session != NULL)
737 panic("%s: pcb->session != NULL\n", __func__);
738 if (pcb->flags & NG_BTSOCKET_RFCOMM_DLC_TIMO)
739 panic("%s: timeout on closed DLC, flags=%#x\n",
740 __func__, pcb->flags);
742 mtx_lock(&ng_btsocket_rfcomm_sockets_mtx);
743 LIST_REMOVE(pcb, next);
744 mtx_unlock(&ng_btsocket_rfcomm_sockets_mtx);
746 mtx_unlock(&pcb->pcb_mtx);
748 mtx_destroy(&pcb->pcb_mtx);
749 bzero(pcb, sizeof(*pcb));
750 FREE(pcb, M_NETGRAPH_BTSOCKET_RFCOMM);
752 soisdisconnected(so);
754 } /* ng_btsocket_rfcomm_detach */
761 ng_btsocket_rfcomm_disconnect(struct socket *so)
763 ng_btsocket_rfcomm_pcb_p pcb = so2rfcomm_pcb(so);
768 mtx_lock(&pcb->pcb_mtx);
770 if (pcb->state == NG_BTSOCKET_RFCOMM_DLC_DISCONNECTING) {
771 mtx_unlock(&pcb->pcb_mtx);
772 return (EINPROGRESS);
775 /* XXX What to do with pending request? */
776 if (pcb->flags & NG_BTSOCKET_RFCOMM_DLC_TIMO)
777 ng_btsocket_rfcomm_untimeout(pcb);
779 switch (pcb->state) {
780 case NG_BTSOCKET_RFCOMM_DLC_CONFIGURING: /* XXX can we get here? */
781 case NG_BTSOCKET_RFCOMM_DLC_CONNECTING: /* XXX can we get here? */
782 case NG_BTSOCKET_RFCOMM_DLC_CONNECTED:
785 * Just change DLC state and enqueue RFCOMM task. It will
786 * queue and send DISC on the DLC.
789 pcb->state = NG_BTSOCKET_RFCOMM_DLC_DISCONNECTING;
790 soisdisconnecting(so);
792 ng_btsocket_rfcomm_task_wakeup();
795 case NG_BTSOCKET_RFCOMM_DLC_CLOSED:
796 case NG_BTSOCKET_RFCOMM_DLC_W4_CONNECT:
800 panic("%s: Invalid DLC state=%d, flags=%#x\n",
801 __func__, pcb->state, pcb->flags);
805 mtx_unlock(&pcb->pcb_mtx);
808 } /* ng_btsocket_rfcomm_disconnect */
811 * Listen on socket. First call to listen() will create listening RFCOMM session
815 ng_btsocket_rfcomm_listen(struct socket *so, int backlog, struct thread *td)
817 ng_btsocket_rfcomm_pcb_p pcb = so2rfcomm_pcb(so), pcb1;
818 ng_btsocket_rfcomm_session_p s = NULL;
819 struct socket *l2so = NULL;
820 int error, socreate_error, usedchannels;
824 if (pcb->channel > 30)
825 return (EADDRNOTAVAIL);
829 mtx_lock(&pcb->pcb_mtx);
831 if (pcb->channel == 0) {
832 mtx_lock(&ng_btsocket_rfcomm_sockets_mtx);
834 LIST_FOREACH(pcb1, &ng_btsocket_rfcomm_sockets, next)
835 if (pcb1->channel != 0 &&
836 bcmp(&pcb1->src, &pcb->src, sizeof(pcb->src)) == 0)
837 usedchannels |= (1 << (pcb1->channel - 1));
839 for (pcb->channel = 30; pcb->channel > 0; pcb->channel --)
840 if (!(usedchannels & (1 << (pcb->channel - 1))))
843 if (pcb->channel == 0) {
844 mtx_unlock(&ng_btsocket_rfcomm_sockets_mtx);
845 mtx_unlock(&pcb->pcb_mtx);
847 return (EADDRNOTAVAIL);
850 mtx_unlock(&ng_btsocket_rfcomm_sockets_mtx);
853 mtx_unlock(&pcb->pcb_mtx);
856 * Note that we will not check for errors in socreate() because
857 * if we failed to create L2CAP socket at this point we still
858 * might have already open session.
861 socreate_error = socreate(PF_BLUETOOTH, &l2so, SOCK_SEQPACKET,
862 BLUETOOTH_PROTO_L2CAP, td->td_ucred, td);
865 * Transition the socket and session into the LISTENING state. Check
866 * for collisions first, as there can only be one.
868 mtx_lock(&ng_btsocket_rfcomm_sessions_mtx);
870 error = solisten_proto_check(so);
875 LIST_FOREACH(s, &ng_btsocket_rfcomm_sessions, next)
876 if (s->state == NG_BTSOCKET_RFCOMM_SESSION_LISTENING)
881 * We need to create default RFCOMM session. Check if we have
882 * L2CAP socket. If l2so == NULL then error has the error code
886 error = socreate_error;
891 * Create default listen RFCOMM session. The default RFCOMM
892 * session will listen on ANY address.
894 * XXX FIXME Note that currently there is no way to adjust MTU
895 * for the default session.
897 error = ng_btsocket_rfcomm_session_create(&s, l2so,
898 NG_HCI_BDADDR_ANY, NULL, td);
904 solisten_proto(so, backlog);
907 mtx_unlock(&ng_btsocket_rfcomm_sessions_mtx);
909 * If we still have an l2so reference here, it's unneeded, so release
915 } /* ng_btsocket_listen */
922 ng_btsocket_rfcomm_peeraddr(struct socket *so, struct sockaddr **nam)
924 ng_btsocket_rfcomm_pcb_p pcb = so2rfcomm_pcb(so);
925 struct sockaddr_rfcomm sa;
930 bcopy(&pcb->dst, &sa.rfcomm_bdaddr, sizeof(sa.rfcomm_bdaddr));
931 sa.rfcomm_channel = pcb->channel;
932 sa.rfcomm_len = sizeof(sa);
933 sa.rfcomm_family = AF_BLUETOOTH;
935 *nam = sodupsockaddr((struct sockaddr *) &sa, M_NOWAIT);
937 return ((*nam == NULL)? ENOMEM : 0);
938 } /* ng_btsocket_rfcomm_peeraddr */
941 * Send data to socket
945 ng_btsocket_rfcomm_send(struct socket *so, int flags, struct mbuf *m,
946 struct sockaddr *nam, struct mbuf *control, struct thread *td)
948 ng_btsocket_rfcomm_pcb_t *pcb = so2rfcomm_pcb(so);
951 /* Check socket and input */
952 if (pcb == NULL || m == NULL || control != NULL) {
957 mtx_lock(&pcb->pcb_mtx);
959 /* Make sure DLC is connected */
960 if (pcb->state != NG_BTSOCKET_RFCOMM_DLC_CONNECTED) {
961 mtx_unlock(&pcb->pcb_mtx);
966 /* Put the packet on the socket's send queue and wakeup RFCOMM task */
967 sbappend(&pcb->so->so_snd, m);
970 if (!(pcb->flags & NG_BTSOCKET_RFCOMM_DLC_SENDING)) {
971 pcb->flags |= NG_BTSOCKET_RFCOMM_DLC_SENDING;
972 error = ng_btsocket_rfcomm_task_wakeup();
975 mtx_unlock(&pcb->pcb_mtx);
977 NG_FREE_M(m); /* checks for != NULL */
981 } /* ng_btsocket_rfcomm_send */
988 ng_btsocket_rfcomm_sockaddr(struct socket *so, struct sockaddr **nam)
990 ng_btsocket_rfcomm_pcb_p pcb = so2rfcomm_pcb(so);
991 struct sockaddr_rfcomm sa;
996 bcopy(&pcb->src, &sa.rfcomm_bdaddr, sizeof(sa.rfcomm_bdaddr));
997 sa.rfcomm_channel = pcb->channel;
998 sa.rfcomm_len = sizeof(sa);
999 sa.rfcomm_family = AF_BLUETOOTH;
1001 *nam = sodupsockaddr((struct sockaddr *) &sa, M_NOWAIT);
1003 return ((*nam == NULL)? ENOMEM : 0);
1004 } /* ng_btsocket_rfcomm_sockaddr */
1007 * Upcall function for L2CAP sockets. Enqueue RFCOMM task.
1011 ng_btsocket_rfcomm_upcall(struct socket *so, void *arg, int waitflag)
1016 panic("%s: so == NULL\n", __func__);
1018 if ((error = ng_btsocket_rfcomm_task_wakeup()) != 0)
1019 NG_BTSOCKET_RFCOMM_ALERT(
1020 "%s: Could not enqueue RFCOMM task, error=%d\n", __func__, error);
1021 } /* ng_btsocket_rfcomm_upcall */
1024 * RFCOMM task. Will handle all RFCOMM sessions in one pass.
1025 * XXX FIXME does not scale very well
1029 ng_btsocket_rfcomm_sessions_task(void *ctx, int pending)
1031 ng_btsocket_rfcomm_session_p s = NULL, s_next = NULL;
1033 mtx_lock(&ng_btsocket_rfcomm_sessions_mtx);
1035 for (s = LIST_FIRST(&ng_btsocket_rfcomm_sessions); s != NULL; ) {
1036 mtx_lock(&s->session_mtx);
1037 s_next = LIST_NEXT(s, next);
1039 ng_btsocket_rfcomm_session_task(s);
1041 if (s->state == NG_BTSOCKET_RFCOMM_SESSION_CLOSED) {
1042 /* Unlink and clean the session */
1043 LIST_REMOVE(s, next);
1045 NG_BT_MBUFQ_DRAIN(&s->outq);
1046 if (!LIST_EMPTY(&s->dlcs))
1047 panic("%s: DLC list is not empty\n", __func__);
1049 /* Close L2CAP socket */
1050 s->l2so->so_upcallarg = NULL;
1051 s->l2so->so_upcall = NULL;
1052 SOCKBUF_LOCK(&s->l2so->so_rcv);
1053 s->l2so->so_rcv.sb_flags &= ~SB_UPCALL;
1054 SOCKBUF_UNLOCK(&s->l2so->so_rcv);
1055 SOCKBUF_LOCK(&s->l2so->so_snd);
1056 s->l2so->so_snd.sb_flags &= ~SB_UPCALL;
1057 SOCKBUF_UNLOCK(&s->l2so->so_snd);
1060 mtx_unlock(&s->session_mtx);
1062 mtx_destroy(&s->session_mtx);
1063 bzero(s, sizeof(*s));
1064 FREE(s, M_NETGRAPH_BTSOCKET_RFCOMM);
1066 mtx_unlock(&s->session_mtx);
1071 mtx_unlock(&ng_btsocket_rfcomm_sessions_mtx);
1072 } /* ng_btsocket_rfcomm_sessions_task */
1075 * Process RFCOMM session. Will handle all RFCOMM sockets in one pass.
1079 ng_btsocket_rfcomm_session_task(ng_btsocket_rfcomm_session_p s)
1081 mtx_assert(&s->session_mtx, MA_OWNED);
1083 if (s->l2so->so_rcv.sb_state & SBS_CANTRCVMORE) {
1084 NG_BTSOCKET_RFCOMM_INFO(
1085 "%s: L2CAP connection has been terminated, so=%p, so_state=%#x, so_count=%d, " \
1086 "state=%d, flags=%#x\n", __func__, s->l2so, s->l2so->so_state,
1087 s->l2so->so_count, s->state, s->flags);
1089 s->state = NG_BTSOCKET_RFCOMM_SESSION_CLOSED;
1090 ng_btsocket_rfcomm_session_clean(s);
1093 /* Now process upcall */
1095 /* Try to accept new L2CAP connection(s) */
1096 case NG_BTSOCKET_RFCOMM_SESSION_LISTENING:
1097 while (ng_btsocket_rfcomm_session_accept(s) == 0)
1101 /* Process the results of the L2CAP connect */
1102 case NG_BTSOCKET_RFCOMM_SESSION_CONNECTING:
1103 ng_btsocket_rfcomm_session_process_pcb(s);
1105 if (ng_btsocket_rfcomm_session_connect(s) != 0) {
1106 s->state = NG_BTSOCKET_RFCOMM_SESSION_CLOSED;
1107 ng_btsocket_rfcomm_session_clean(s);
1111 /* Try to receive/send more data */
1112 case NG_BTSOCKET_RFCOMM_SESSION_CONNECTED:
1113 case NG_BTSOCKET_RFCOMM_SESSION_OPEN:
1114 case NG_BTSOCKET_RFCOMM_SESSION_DISCONNECTING:
1115 ng_btsocket_rfcomm_session_process_pcb(s);
1117 if (ng_btsocket_rfcomm_session_receive(s) != 0) {
1118 s->state = NG_BTSOCKET_RFCOMM_SESSION_CLOSED;
1119 ng_btsocket_rfcomm_session_clean(s);
1120 } else if (ng_btsocket_rfcomm_session_send(s) != 0) {
1121 s->state = NG_BTSOCKET_RFCOMM_SESSION_CLOSED;
1122 ng_btsocket_rfcomm_session_clean(s);
1126 case NG_BTSOCKET_RFCOMM_SESSION_CLOSED:
1130 panic("%s: Invalid session state=%d, flags=%#x\n",
1131 __func__, s->state, s->flags);
1134 } /* ng_btsocket_rfcomm_session_task */
1137 * Process RFCOMM connection indicator. Caller must hold s->session_mtx
1140 static ng_btsocket_rfcomm_pcb_p
1141 ng_btsocket_rfcomm_connect_ind(ng_btsocket_rfcomm_session_p s, int channel)
1143 ng_btsocket_rfcomm_pcb_p pcb = NULL, pcb1 = NULL;
1144 ng_btsocket_l2cap_pcb_p l2pcb = NULL;
1145 struct socket *so1 = NULL;
1147 mtx_assert(&s->session_mtx, MA_OWNED);
1150 * Try to find RFCOMM socket that listens on given source address
1151 * and channel. This will return the best possible match.
1154 l2pcb = so2l2cap_pcb(s->l2so);
1155 pcb = ng_btsocket_rfcomm_pcb_listener(&l2pcb->src, channel);
1160 * Check the pending connections queue and if we have space then
1161 * create new socket and set proper source and destination address,
1165 mtx_lock(&pcb->pcb_mtx);
1167 if (pcb->so->so_qlen <= pcb->so->so_qlimit)
1168 so1 = sonewconn(pcb->so, 0);
1170 mtx_unlock(&pcb->pcb_mtx);
1176 * If we got here than we have created new socket. So complete the
1177 * connection. Set source and destination address from the session.
1180 pcb1 = so2rfcomm_pcb(so1);
1182 panic("%s: pcb1 == NULL\n", __func__);
1184 mtx_lock(&pcb1->pcb_mtx);
1186 bcopy(&l2pcb->src, &pcb1->src, sizeof(pcb1->src));
1187 bcopy(&l2pcb->dst, &pcb1->dst, sizeof(pcb1->dst));
1188 pcb1->channel = channel;
1190 /* Link new DLC to the session. We already hold s->session_mtx */
1191 LIST_INSERT_HEAD(&s->dlcs, pcb1, session_next);
1194 mtx_unlock(&pcb1->pcb_mtx);
1197 } /* ng_btsocket_rfcomm_connect_ind */
1200 * Process RFCOMM connect confirmation. Caller must hold s->session_mtx.
1204 ng_btsocket_rfcomm_connect_cfm(ng_btsocket_rfcomm_session_p s)
1206 ng_btsocket_rfcomm_pcb_p pcb = NULL, pcb_next = NULL;
1209 mtx_assert(&s->session_mtx, MA_OWNED);
1212 * Wake up all waiting sockets and send PN request for each of them.
1213 * Note that timeout already been set in ng_btsocket_rfcomm_connect()
1215 * Note: cannot use LIST_FOREACH because ng_btsocket_rfcomm_pcb_kill
1216 * will unlink DLC from the session
1219 for (pcb = LIST_FIRST(&s->dlcs); pcb != NULL; ) {
1220 mtx_lock(&pcb->pcb_mtx);
1221 pcb_next = LIST_NEXT(pcb, session_next);
1223 if (pcb->state == NG_BTSOCKET_RFCOMM_DLC_W4_CONNECT) {
1225 bcopy(&so2l2cap_pcb(s->l2so)->src, &pcb->src,
1228 error = ng_btsocket_rfcomm_send_pn(pcb);
1230 pcb->state = NG_BTSOCKET_RFCOMM_DLC_CONFIGURING;
1232 ng_btsocket_rfcomm_pcb_kill(pcb, error);
1235 mtx_unlock(&pcb->pcb_mtx);
1238 } /* ng_btsocket_rfcomm_connect_cfm */
1240 /*****************************************************************************
1241 *****************************************************************************
1243 *****************************************************************************
1244 *****************************************************************************/
1247 * Create new RFCOMM session. That function WILL NOT take ownership over l2so.
1248 * Caller MUST free l2so if function failed.
1252 ng_btsocket_rfcomm_session_create(ng_btsocket_rfcomm_session_p *sp,
1253 struct socket *l2so, bdaddr_p src, bdaddr_p dst,
1256 ng_btsocket_rfcomm_session_p s = NULL;
1257 struct sockaddr_l2cap l2sa;
1258 struct sockopt l2sopt;
1262 mtx_assert(&ng_btsocket_rfcomm_sessions_mtx, MA_OWNED);
1264 /* Allocate the RFCOMM session */
1265 MALLOC(s, ng_btsocket_rfcomm_session_p, sizeof(*s),
1266 M_NETGRAPH_BTSOCKET_RFCOMM, M_NOWAIT | M_ZERO);
1271 s->mtu = RFCOMM_DEFAULT_MTU;
1273 s->state = NG_BTSOCKET_RFCOMM_SESSION_CLOSED;
1274 NG_BT_MBUFQ_INIT(&s->outq, ifqmaxlen);
1277 * XXX Mark session mutex as DUPOK to prevent "duplicated lock of
1278 * the same type" message. When accepting new L2CAP connection
1279 * ng_btsocket_rfcomm_session_accept() holds both session mutexes
1280 * for "old" (accepting) session and "new" (created) session.
1283 mtx_init(&s->session_mtx, "btsocks_rfcomm_session_mtx", NULL,
1286 LIST_INIT(&s->dlcs);
1288 /* Prepare L2CAP socket */
1289 l2so->so_upcallarg = NULL;
1290 l2so->so_upcall = ng_btsocket_rfcomm_upcall;
1291 SOCKBUF_LOCK(&l2so->so_rcv);
1292 l2so->so_rcv.sb_flags |= SB_UPCALL;
1293 SOCKBUF_UNLOCK(&l2so->so_rcv);
1294 SOCKBUF_LOCK(&l2so->so_snd);
1295 l2so->so_snd.sb_flags |= SB_UPCALL;
1296 SOCKBUF_UNLOCK(&l2so->so_snd);
1297 l2so->so_state |= SS_NBIO;
1300 mtx_lock(&s->session_mtx);
1303 * "src" == NULL and "dst" == NULL means just create session.
1304 * caller must do the rest
1307 if (src == NULL && dst == NULL)
1311 * Set incoming MTU on L2CAP socket. It is RFCOMM session default MTU
1312 * plus 5 bytes: RFCOMM frame header, one extra byte for length and one
1313 * extra byte for credits.
1316 mtu = s->mtu + sizeof(struct rfcomm_frame_hdr) + 1 + 1;
1318 l2sopt.sopt_dir = SOPT_SET;
1319 l2sopt.sopt_level = SOL_L2CAP;
1320 l2sopt.sopt_name = SO_L2CAP_IMTU;
1321 l2sopt.sopt_val = (void *) &mtu;
1322 l2sopt.sopt_valsize = sizeof(mtu);
1323 l2sopt.sopt_td = NULL;
1325 error = sosetopt(s->l2so, &l2sopt);
1329 /* Bind socket to "src" address */
1330 l2sa.l2cap_len = sizeof(l2sa);
1331 l2sa.l2cap_family = AF_BLUETOOTH;
1332 l2sa.l2cap_psm = (dst == NULL)? htole16(NG_L2CAP_PSM_RFCOMM) : 0;
1333 bcopy(src, &l2sa.l2cap_bdaddr, sizeof(l2sa.l2cap_bdaddr));
1335 error = sobind(s->l2so, (struct sockaddr *) &l2sa, td);
1339 /* If "dst" is not NULL then initiate connect(), otherwise listen() */
1342 s->state = NG_BTSOCKET_RFCOMM_SESSION_LISTENING;
1344 error = solisten(s->l2so, 10, td);
1348 s->flags = NG_BTSOCKET_RFCOMM_SESSION_INITIATOR;
1349 s->state = NG_BTSOCKET_RFCOMM_SESSION_CONNECTING;
1351 l2sa.l2cap_len = sizeof(l2sa);
1352 l2sa.l2cap_family = AF_BLUETOOTH;
1353 l2sa.l2cap_psm = htole16(NG_L2CAP_PSM_RFCOMM);
1354 bcopy(dst, &l2sa.l2cap_bdaddr, sizeof(l2sa.l2cap_bdaddr));
1356 error = soconnect(s->l2so, (struct sockaddr *) &l2sa, td);
1362 LIST_INSERT_HEAD(&ng_btsocket_rfcomm_sessions, s, next);
1365 mtx_unlock(&s->session_mtx);
1370 mtx_unlock(&s->session_mtx);
1372 /* Return L2CAP socket back to its original state */
1373 l2so->so_upcallarg = NULL;
1374 l2so->so_upcall = NULL;
1375 SOCKBUF_LOCK(&l2so->so_rcv);
1376 l2so->so_rcv.sb_flags &= ~SB_UPCALL;
1377 SOCKBUF_UNLOCK(&l2so->so_rcv);
1378 SOCKBUF_LOCK(&l2so->so_snd);
1379 l2so->so_snd.sb_flags &= ~SB_UPCALL;
1380 SOCKBUF_UNLOCK(&l2so->so_snd);
1381 l2so->so_state &= ~SS_NBIO;
1383 mtx_destroy(&s->session_mtx);
1384 bzero(s, sizeof(*s));
1385 FREE(s, M_NETGRAPH_BTSOCKET_RFCOMM);
1388 } /* ng_btsocket_rfcomm_session_create */
1391 * Process accept() on RFCOMM session
1392 * XXX FIXME locking for "l2so"?
1396 ng_btsocket_rfcomm_session_accept(ng_btsocket_rfcomm_session_p s0)
1398 struct socket *l2so = NULL;
1399 struct sockaddr_l2cap *l2sa = NULL;
1400 ng_btsocket_l2cap_pcb_t *l2pcb = NULL;
1401 ng_btsocket_rfcomm_session_p s = NULL;
1404 mtx_assert(&ng_btsocket_rfcomm_sessions_mtx, MA_OWNED);
1405 mtx_assert(&s0->session_mtx, MA_OWNED);
1407 /* Check if there is a complete L2CAP connection in the queue */
1408 if ((error = s0->l2so->so_error) != 0) {
1409 NG_BTSOCKET_RFCOMM_ERR(
1410 "%s: Could not accept connection on L2CAP socket, error=%d\n", __func__, error);
1411 s0->l2so->so_error = 0;
1417 if (TAILQ_EMPTY(&s0->l2so->so_comp)) {
1419 if (s0->l2so->so_rcv.sb_state & SBS_CANTRCVMORE)
1420 return (ECONNABORTED);
1421 return (EWOULDBLOCK);
1424 /* Accept incoming L2CAP connection */
1425 l2so = TAILQ_FIRST(&s0->l2so->so_comp);
1427 panic("%s: l2so == NULL\n", __func__);
1429 TAILQ_REMOVE(&s0->l2so->so_comp, l2so, so_list);
1430 s0->l2so->so_qlen --;
1431 l2so->so_qstate &= ~SQ_COMP;
1432 l2so->so_head = NULL;
1435 l2so->so_state |= SS_NBIO;
1439 error = soaccept(l2so, (struct sockaddr **) &l2sa);
1441 NG_BTSOCKET_RFCOMM_ERR(
1442 "%s: soaccept() on L2CAP socket failed, error=%d\n", __func__, error);
1449 * Check if there is already active RFCOMM session between two devices.
1450 * If so then close L2CAP connection. We only support one RFCOMM session
1451 * between each pair of devices. Note that here we assume session in any
1452 * state. The session even could be in the middle of disconnecting.
1455 l2pcb = so2l2cap_pcb(l2so);
1456 s = ng_btsocket_rfcomm_session_by_addr(&l2pcb->src, &l2pcb->dst);
1458 /* Create a new RFCOMM session */
1459 error = ng_btsocket_rfcomm_session_create(&s, l2so, NULL, NULL,
1460 curthread /* XXX */);
1462 mtx_lock(&s->session_mtx);
1465 s->state = NG_BTSOCKET_RFCOMM_SESSION_CONNECTED;
1468 * Adjust MTU on incomming connection. Reserve 5 bytes:
1469 * RFCOMM frame header, one extra byte for length and
1470 * one extra byte for credits.
1473 s->mtu = min(l2pcb->imtu, l2pcb->omtu) -
1474 sizeof(struct rfcomm_frame_hdr) - 1 - 1;
1476 mtx_unlock(&s->session_mtx);
1478 NG_BTSOCKET_RFCOMM_ALERT(
1479 "%s: Failed to create new RFCOMM session, error=%d\n", __func__, error);
1484 NG_BTSOCKET_RFCOMM_WARN(
1485 "%s: Rejecting duplicating RFCOMM session between src=%x:%x:%x:%x:%x:%x and " \
1486 "dst=%x:%x:%x:%x:%x:%x, state=%d, flags=%#x\n", __func__,
1487 l2pcb->src.b[5], l2pcb->src.b[4], l2pcb->src.b[3],
1488 l2pcb->src.b[2], l2pcb->src.b[1], l2pcb->src.b[0],
1489 l2pcb->dst.b[5], l2pcb->dst.b[4], l2pcb->dst.b[3],
1490 l2pcb->dst.b[2], l2pcb->dst.b[1], l2pcb->dst.b[0],
1491 s->state, s->flags);
1498 } /* ng_btsocket_rfcomm_session_accept */
1501 * Process connect() on RFCOMM session
1502 * XXX FIXME locking for "l2so"?
1506 ng_btsocket_rfcomm_session_connect(ng_btsocket_rfcomm_session_p s)
1508 ng_btsocket_l2cap_pcb_p l2pcb = so2l2cap_pcb(s->l2so);
1511 mtx_assert(&s->session_mtx, MA_OWNED);
1513 /* First check if connection has failed */
1514 if ((error = s->l2so->so_error) != 0) {
1515 s->l2so->so_error = 0;
1517 NG_BTSOCKET_RFCOMM_ERR(
1518 "%s: Could not connect RFCOMM session, error=%d, state=%d, flags=%#x\n",
1519 __func__, error, s->state, s->flags);
1524 /* Is connection still in progress? */
1525 if (s->l2so->so_state & SS_ISCONNECTING)
1529 * If we got here then we are connected. Send SABM on DLCI 0 to
1530 * open multiplexor channel.
1534 s->state = NG_BTSOCKET_RFCOMM_SESSION_CONNECTED;
1537 * Adjust MTU on outgoing connection. Reserve 5 bytes: RFCOMM
1538 * frame header, one extra byte for length and one extra byte
1542 s->mtu = min(l2pcb->imtu, l2pcb->omtu) -
1543 sizeof(struct rfcomm_frame_hdr) - 1 - 1;
1545 error = ng_btsocket_rfcomm_send_command(s,RFCOMM_FRAME_SABM,0);
1547 error = ng_btsocket_rfcomm_task_wakeup();
1551 }/* ng_btsocket_rfcomm_session_connect */
1554 * Receive data on RFCOMM session
1555 * XXX FIXME locking for "l2so"?
1559 ng_btsocket_rfcomm_session_receive(ng_btsocket_rfcomm_session_p s)
1561 struct mbuf *m = NULL;
1563 int more, flags, error;
1565 mtx_assert(&s->session_mtx, MA_OWNED);
1567 /* Can we read from the L2CAP socket? */
1568 if (!soreadable(s->l2so))
1571 /* First check for error on L2CAP socket */
1572 if ((error = s->l2so->so_error) != 0) {
1573 s->l2so->so_error = 0;
1575 NG_BTSOCKET_RFCOMM_ERR(
1576 "%s: Could not receive data from L2CAP socket, error=%d, state=%d, flags=%#x\n",
1577 __func__, error, s->state, s->flags);
1583 * Read all packets from the L2CAP socket.
1584 * XXX FIXME/VERIFY is that correct? For now use m->m_nextpkt as
1585 * indication that there is more packets on the socket's buffer.
1586 * Also what should we use in uio.uio_resid?
1587 * May be s->mtu + sizeof(struct rfcomm_frame_hdr) + 1 + 1?
1590 for (more = 1; more; ) {
1591 /* Try to get next packet from socket */
1592 bzero(&uio, sizeof(uio));
1593 /* uio.uio_td = NULL; */
1594 uio.uio_resid = 1000000000;
1595 flags = MSG_DONTWAIT;
1598 error = soreceive(s->l2so, NULL, &uio, &m,
1599 (struct mbuf **) NULL, &flags);
1601 if (error == EWOULDBLOCK)
1602 return (0); /* XXX can happen? */
1604 NG_BTSOCKET_RFCOMM_ERR(
1605 "%s: Could not receive data from L2CAP socket, error=%d\n", __func__, error);
1610 more = (m->m_nextpkt != NULL);
1611 m->m_nextpkt = NULL;
1613 ng_btsocket_rfcomm_receive_frame(s, m);
1617 } /* ng_btsocket_rfcomm_session_receive */
1620 * Send data on RFCOMM session
1621 * XXX FIXME locking for "l2so"?
1625 ng_btsocket_rfcomm_session_send(ng_btsocket_rfcomm_session_p s)
1627 struct mbuf *m = NULL;
1630 mtx_assert(&s->session_mtx, MA_OWNED);
1632 /* Send as much as we can from the session queue */
1633 while (sowriteable(s->l2so)) {
1634 /* Check if socket still OK */
1635 if ((error = s->l2so->so_error) != 0) {
1636 s->l2so->so_error = 0;
1638 NG_BTSOCKET_RFCOMM_ERR(
1639 "%s: Detected error=%d on L2CAP socket, state=%d, flags=%#x\n",
1640 __func__, error, s->state, s->flags);
1645 NG_BT_MBUFQ_DEQUEUE(&s->outq, m);
1647 return (0); /* we are done */
1649 /* Call send function on the L2CAP socket */
1650 error = (*s->l2so->so_proto->pr_usrreqs->pru_send)(s->l2so,
1651 0, m, NULL, NULL, curthread /* XXX */);
1653 NG_BTSOCKET_RFCOMM_ERR(
1654 "%s: Could not send data to L2CAP socket, error=%d\n", __func__, error);
1661 } /* ng_btsocket_rfcomm_session_send */
1664 * Close and disconnect all DLCs for the given session. Caller must hold
1665 * s->sesson_mtx. Will wakeup session.
1669 ng_btsocket_rfcomm_session_clean(ng_btsocket_rfcomm_session_p s)
1671 ng_btsocket_rfcomm_pcb_p pcb = NULL, pcb_next = NULL;
1674 mtx_assert(&s->session_mtx, MA_OWNED);
1677 * Note: cannot use LIST_FOREACH because ng_btsocket_rfcomm_pcb_kill
1678 * will unlink DLC from the session
1681 for (pcb = LIST_FIRST(&s->dlcs); pcb != NULL; ) {
1682 mtx_lock(&pcb->pcb_mtx);
1683 pcb_next = LIST_NEXT(pcb, session_next);
1685 NG_BTSOCKET_RFCOMM_INFO(
1686 "%s: Disconnecting dlci=%d, state=%d, flags=%#x\n",
1687 __func__, pcb->dlci, pcb->state, pcb->flags);
1689 if (pcb->state == NG_BTSOCKET_RFCOMM_DLC_CONNECTED)
1692 error = ECONNREFUSED;
1694 ng_btsocket_rfcomm_pcb_kill(pcb, error);
1696 mtx_unlock(&pcb->pcb_mtx);
1699 } /* ng_btsocket_rfcomm_session_clean */
1702 * Process all DLCs on the session. Caller MUST hold s->session_mtx.
1706 ng_btsocket_rfcomm_session_process_pcb(ng_btsocket_rfcomm_session_p s)
1708 ng_btsocket_rfcomm_pcb_p pcb = NULL, pcb_next = NULL;
1711 mtx_assert(&s->session_mtx, MA_OWNED);
1714 * Note: cannot use LIST_FOREACH because ng_btsocket_rfcomm_pcb_kill
1715 * will unlink DLC from the session
1718 for (pcb = LIST_FIRST(&s->dlcs); pcb != NULL; ) {
1719 mtx_lock(&pcb->pcb_mtx);
1720 pcb_next = LIST_NEXT(pcb, session_next);
1722 switch (pcb->state) {
1725 * If DLC in W4_CONNECT state then we should check for both
1726 * timeout and detach.
1729 case NG_BTSOCKET_RFCOMM_DLC_W4_CONNECT:
1730 if (pcb->flags & NG_BTSOCKET_RFCOMM_DLC_DETACHED)
1731 ng_btsocket_rfcomm_pcb_kill(pcb, 0);
1732 else if (pcb->flags & NG_BTSOCKET_RFCOMM_DLC_TIMEDOUT)
1733 ng_btsocket_rfcomm_pcb_kill(pcb, ETIMEDOUT);
1737 * If DLC in CONFIGURING or CONNECTING state then we only
1738 * should check for timeout. If detach() was called then
1739 * DLC will be moved into DISCONNECTING state.
1742 case NG_BTSOCKET_RFCOMM_DLC_CONFIGURING:
1743 case NG_BTSOCKET_RFCOMM_DLC_CONNECTING:
1744 if (pcb->flags & NG_BTSOCKET_RFCOMM_DLC_TIMEDOUT)
1745 ng_btsocket_rfcomm_pcb_kill(pcb, ETIMEDOUT);
1749 * If DLC in CONNECTED state then we need to send data (if any)
1750 * from the socket's send queue. Note that we will send data
1751 * from either all sockets or none. This may overload session's
1752 * outgoing queue (but we do not check for that).
1754 * XXX FIXME need scheduler for RFCOMM sockets
1757 case NG_BTSOCKET_RFCOMM_DLC_CONNECTED:
1758 error = ng_btsocket_rfcomm_pcb_send(pcb, ALOT);
1760 ng_btsocket_rfcomm_pcb_kill(pcb, error);
1764 * If DLC in DISCONNECTING state then we must send DISC frame.
1765 * Note that if DLC has timeout set then we do not need to
1766 * resend DISC frame.
1768 * XXX FIXME need to drain all data from the socket's queue
1769 * if LINGER option was set
1772 case NG_BTSOCKET_RFCOMM_DLC_DISCONNECTING:
1773 if (!(pcb->flags & NG_BTSOCKET_RFCOMM_DLC_TIMO)) {
1774 error = ng_btsocket_rfcomm_send_command(
1775 pcb->session, RFCOMM_FRAME_DISC,
1778 ng_btsocket_rfcomm_timeout(pcb);
1780 ng_btsocket_rfcomm_pcb_kill(pcb, error);
1781 } else if (pcb->flags & NG_BTSOCKET_RFCOMM_DLC_TIMEDOUT)
1782 ng_btsocket_rfcomm_pcb_kill(pcb, ETIMEDOUT);
1785 /* case NG_BTSOCKET_RFCOMM_DLC_CLOSED: */
1787 panic("%s: Invalid DLC state=%d, flags=%#x\n",
1788 __func__, pcb->state, pcb->flags);
1792 mtx_unlock(&pcb->pcb_mtx);
1795 } /* ng_btsocket_rfcomm_session_process_pcb */
1798 * Find RFCOMM session between "src" and "dst".
1799 * Caller MUST hold ng_btsocket_rfcomm_sessions_mtx.
1802 static ng_btsocket_rfcomm_session_p
1803 ng_btsocket_rfcomm_session_by_addr(bdaddr_p src, bdaddr_p dst)
1805 ng_btsocket_rfcomm_session_p s = NULL;
1806 ng_btsocket_l2cap_pcb_p l2pcb = NULL;
1809 mtx_assert(&ng_btsocket_rfcomm_sessions_mtx, MA_OWNED);
1811 any_src = (bcmp(src, NG_HCI_BDADDR_ANY, sizeof(*src)) == 0);
1813 LIST_FOREACH(s, &ng_btsocket_rfcomm_sessions, next) {
1814 l2pcb = so2l2cap_pcb(s->l2so);
1816 if ((any_src || bcmp(&l2pcb->src, src, sizeof(*src)) == 0) &&
1817 bcmp(&l2pcb->dst, dst, sizeof(*dst)) == 0)
1822 } /* ng_btsocket_rfcomm_session_by_addr */
1824 /*****************************************************************************
1825 *****************************************************************************
1827 *****************************************************************************
1828 *****************************************************************************/
1831 * Process incoming RFCOMM frame. Caller must hold s->session_mtx.
1832 * XXX FIXME check frame length
1836 ng_btsocket_rfcomm_receive_frame(ng_btsocket_rfcomm_session_p s,
1839 struct rfcomm_frame_hdr *hdr = NULL;
1840 struct mbuf *m = NULL;
1842 u_int8_t dlci, type;
1845 mtx_assert(&s->session_mtx, MA_OWNED);
1847 /* Pullup as much as we can into first mbuf (for direct access) */
1848 length = min(m0->m_pkthdr.len, MHLEN);
1849 if (m0->m_len < length) {
1850 if ((m0 = m_pullup(m0, length)) == NULL) {
1851 NG_BTSOCKET_RFCOMM_ALERT(
1852 "%s: m_pullup(%d) failed\n", __func__, length);
1858 hdr = mtod(m0, struct rfcomm_frame_hdr *);
1859 dlci = RFCOMM_DLCI(hdr->address);
1860 type = RFCOMM_TYPE(hdr->control);
1862 /* Test EA bit in length. If not set then we have 2 bytes of length */
1863 if (!RFCOMM_EA(hdr->length)) {
1864 bcopy(&hdr->length, &length, sizeof(length));
1865 length = le16toh(length) >> 1;
1866 m_adj(m0, sizeof(*hdr) + 1);
1868 length = hdr->length >> 1;
1869 m_adj(m0, sizeof(*hdr));
1872 NG_BTSOCKET_RFCOMM_INFO(
1873 "%s: Got frame type=%#x, dlci=%d, length=%d, cr=%d, pf=%d, len=%d\n",
1874 __func__, type, dlci, length, RFCOMM_CR(hdr->address),
1875 RFCOMM_PF(hdr->control), m0->m_pkthdr.len);
1878 * Get FCS (the last byte in the frame)
1879 * XXX this will not work if mbuf chain ends with empty mbuf.
1880 * XXX let's hope it never happens :)
1883 for (m = m0; m->m_next != NULL; m = m->m_next)
1886 panic("%s: Empty mbuf at the end of the chain, len=%d\n",
1887 __func__, m->m_len);
1890 * Check FCS. We only need to calculate FCS on first 2 or 3 bytes
1891 * and already m_pullup'ed mbuf chain, so it should be safe.
1894 if (ng_btsocket_rfcomm_check_fcs((u_int8_t *) hdr, type, m->m_data[m->m_len - 1])) {
1895 NG_BTSOCKET_RFCOMM_ERR(
1896 "%s: Invalid RFCOMM packet. Bad checksum\n", __func__);
1902 m_adj(m0, -1); /* Trim FCS byte */
1905 * Process RFCOMM frame.
1907 * From TS 07.10 spec
1909 * "... In the case where a SABM or DISC command with the P bit set
1910 * to 0 is received then the received frame shall be discarded..."
1912 * "... If a unsolicited DM response is received then the frame shall
1913 * be processed irrespective of the P/F setting... "
1915 * "... The station may transmit response frames with the F bit set
1916 * to 0 at any opportunity on an asynchronous basis. However, in the
1917 * case where a UA response is received with the F bit set to 0 then
1918 * the received frame shall be discarded..."
1920 * From Bluetooth spec
1922 * "... When credit based flow control is being used, the meaning of
1923 * the P/F bit in the control field of the RFCOMM header is redefined
1924 * for UIH frames..."
1928 case RFCOMM_FRAME_SABM:
1929 if (RFCOMM_PF(hdr->control))
1930 error = ng_btsocket_rfcomm_receive_sabm(s, dlci);
1933 case RFCOMM_FRAME_DISC:
1934 if (RFCOMM_PF(hdr->control))
1935 error = ng_btsocket_rfcomm_receive_disc(s, dlci);
1938 case RFCOMM_FRAME_UA:
1939 if (RFCOMM_PF(hdr->control))
1940 error = ng_btsocket_rfcomm_receive_ua(s, dlci);
1943 case RFCOMM_FRAME_DM:
1944 error = ng_btsocket_rfcomm_receive_dm(s, dlci);
1947 case RFCOMM_FRAME_UIH:
1949 error = ng_btsocket_rfcomm_receive_mcc(s, m0);
1951 error = ng_btsocket_rfcomm_receive_uih(s, dlci,
1952 RFCOMM_PF(hdr->control), m0);
1958 NG_BTSOCKET_RFCOMM_ERR(
1959 "%s: Invalid RFCOMM packet. Unknown type=%#x\n", __func__, type);
1967 } /* ng_btsocket_rfcomm_receive_frame */
1970 * Process RFCOMM SABM frame
1974 ng_btsocket_rfcomm_receive_sabm(ng_btsocket_rfcomm_session_p s, int dlci)
1976 ng_btsocket_rfcomm_pcb_p pcb = NULL;
1979 mtx_assert(&s->session_mtx, MA_OWNED);
1981 NG_BTSOCKET_RFCOMM_INFO(
1982 "%s: Got SABM, session state=%d, flags=%#x, mtu=%d, dlci=%d\n",
1983 __func__, s->state, s->flags, s->mtu, dlci);
1985 /* DLCI == 0 means open multiplexor channel */
1988 case NG_BTSOCKET_RFCOMM_SESSION_CONNECTED:
1989 case NG_BTSOCKET_RFCOMM_SESSION_OPEN:
1990 error = ng_btsocket_rfcomm_send_command(s,
1991 RFCOMM_FRAME_UA, dlci);
1993 s->state = NG_BTSOCKET_RFCOMM_SESSION_OPEN;
1994 ng_btsocket_rfcomm_connect_cfm(s);
1996 s->state = NG_BTSOCKET_RFCOMM_SESSION_CLOSED;
1997 ng_btsocket_rfcomm_session_clean(s);
2002 NG_BTSOCKET_RFCOMM_WARN(
2003 "%s: Got SABM for session in invalid state state=%d, flags=%#x\n",
2004 __func__, s->state, s->flags);
2012 /* Make sure multiplexor channel is open */
2013 if (s->state != NG_BTSOCKET_RFCOMM_SESSION_OPEN) {
2014 NG_BTSOCKET_RFCOMM_ERR(
2015 "%s: Got SABM for dlci=%d with mulitplexor channel closed, state=%d, " \
2016 "flags=%#x\n", __func__, dlci, s->state, s->flags);
2022 * Check if we have this DLCI. This might happen when remote
2023 * peer uses PN command before actual open (SABM) happens.
2026 pcb = ng_btsocket_rfcomm_pcb_by_dlci(s, dlci);
2028 mtx_lock(&pcb->pcb_mtx);
2030 if (pcb->state != NG_BTSOCKET_RFCOMM_DLC_CONNECTING) {
2031 NG_BTSOCKET_RFCOMM_ERR(
2032 "%s: Got SABM for dlci=%d in invalid state=%d, flags=%#x\n",
2033 __func__, dlci, pcb->state, pcb->flags);
2034 mtx_unlock(&pcb->pcb_mtx);
2039 ng_btsocket_rfcomm_untimeout(pcb);
2041 error = ng_btsocket_rfcomm_send_command(s,RFCOMM_FRAME_UA,dlci);
2043 error = ng_btsocket_rfcomm_send_msc(pcb);
2046 pcb->state = NG_BTSOCKET_RFCOMM_DLC_CONNECTED;
2047 soisconnected(pcb->so);
2049 ng_btsocket_rfcomm_pcb_kill(pcb, error);
2051 mtx_unlock(&pcb->pcb_mtx);
2057 * We do not have requested DLCI, so it must be an incoming connection
2058 * with default parameters. Try to accept it.
2061 pcb = ng_btsocket_rfcomm_connect_ind(s, RFCOMM_SRVCHANNEL(dlci));
2063 mtx_lock(&pcb->pcb_mtx);
2067 error = ng_btsocket_rfcomm_send_command(s,RFCOMM_FRAME_UA,dlci);
2069 error = ng_btsocket_rfcomm_send_msc(pcb);
2072 pcb->state = NG_BTSOCKET_RFCOMM_DLC_CONNECTED;
2073 soisconnected(pcb->so);
2075 ng_btsocket_rfcomm_pcb_kill(pcb, error);
2077 mtx_unlock(&pcb->pcb_mtx);
2079 /* Nobody is listen()ing on the requested DLCI */
2080 error = ng_btsocket_rfcomm_send_command(s,RFCOMM_FRAME_DM,dlci);
2083 } /* ng_btsocket_rfcomm_receive_sabm */
2086 * Process RFCOMM DISC frame
2090 ng_btsocket_rfcomm_receive_disc(ng_btsocket_rfcomm_session_p s, int dlci)
2092 ng_btsocket_rfcomm_pcb_p pcb = NULL;
2095 mtx_assert(&s->session_mtx, MA_OWNED);
2097 NG_BTSOCKET_RFCOMM_INFO(
2098 "%s: Got DISC, session state=%d, flags=%#x, mtu=%d, dlci=%d\n",
2099 __func__, s->state, s->flags, s->mtu, dlci);
2101 /* DLCI == 0 means close multiplexor channel */
2103 /* XXX FIXME assume that remote side will close the socket */
2104 error = ng_btsocket_rfcomm_send_command(s, RFCOMM_FRAME_UA, 0);
2106 if (s->state == NG_BTSOCKET_RFCOMM_SESSION_DISCONNECTING)
2107 s->state = NG_BTSOCKET_RFCOMM_SESSION_CLOSED; /* XXX */
2109 s->state = NG_BTSOCKET_RFCOMM_SESSION_DISCONNECTING;
2111 s->state = NG_BTSOCKET_RFCOMM_SESSION_CLOSED; /* XXX */
2113 ng_btsocket_rfcomm_session_clean(s);
2115 pcb = ng_btsocket_rfcomm_pcb_by_dlci(s, dlci);
2119 mtx_lock(&pcb->pcb_mtx);
2121 NG_BTSOCKET_RFCOMM_INFO(
2122 "%s: Got DISC for dlci=%d, state=%d, flags=%#x\n",
2123 __func__, dlci, pcb->state, pcb->flags);
2125 error = ng_btsocket_rfcomm_send_command(s,
2126 RFCOMM_FRAME_UA, dlci);
2128 if (pcb->state == NG_BTSOCKET_RFCOMM_DLC_CONNECTED)
2133 ng_btsocket_rfcomm_pcb_kill(pcb, err);
2135 mtx_unlock(&pcb->pcb_mtx);
2137 NG_BTSOCKET_RFCOMM_WARN(
2138 "%s: Got DISC for non-existing dlci=%d\n", __func__, dlci);
2140 error = ng_btsocket_rfcomm_send_command(s,
2141 RFCOMM_FRAME_DM, dlci);
2146 } /* ng_btsocket_rfcomm_receive_disc */
2149 * Process RFCOMM UA frame
2153 ng_btsocket_rfcomm_receive_ua(ng_btsocket_rfcomm_session_p s, int dlci)
2155 ng_btsocket_rfcomm_pcb_p pcb = NULL;
2158 mtx_assert(&s->session_mtx, MA_OWNED);
2160 NG_BTSOCKET_RFCOMM_INFO(
2161 "%s: Got UA, session state=%d, flags=%#x, mtu=%d, dlci=%d\n",
2162 __func__, s->state, s->flags, s->mtu, dlci);
2164 /* dlci == 0 means multiplexor channel */
2167 case NG_BTSOCKET_RFCOMM_SESSION_CONNECTED:
2168 s->state = NG_BTSOCKET_RFCOMM_SESSION_OPEN;
2169 ng_btsocket_rfcomm_connect_cfm(s);
2172 case NG_BTSOCKET_RFCOMM_SESSION_DISCONNECTING:
2173 s->state = NG_BTSOCKET_RFCOMM_SESSION_CLOSED;
2174 ng_btsocket_rfcomm_session_clean(s);
2178 NG_BTSOCKET_RFCOMM_WARN(
2179 "%s: Got UA for session in invalid state=%d(%d), flags=%#x, mtu=%d\n",
2180 __func__, s->state, INITIATOR(s), s->flags,
2189 /* Check if we have this DLCI */
2190 pcb = ng_btsocket_rfcomm_pcb_by_dlci(s, dlci);
2192 mtx_lock(&pcb->pcb_mtx);
2194 NG_BTSOCKET_RFCOMM_INFO(
2195 "%s: Got UA for dlci=%d, state=%d, flags=%#x\n",
2196 __func__, dlci, pcb->state, pcb->flags);
2198 switch (pcb->state) {
2199 case NG_BTSOCKET_RFCOMM_DLC_CONNECTING:
2200 ng_btsocket_rfcomm_untimeout(pcb);
2202 error = ng_btsocket_rfcomm_send_msc(pcb);
2204 pcb->state = NG_BTSOCKET_RFCOMM_DLC_CONNECTED;
2205 soisconnected(pcb->so);
2209 case NG_BTSOCKET_RFCOMM_DLC_DISCONNECTING:
2210 ng_btsocket_rfcomm_pcb_kill(pcb, 0);
2214 NG_BTSOCKET_RFCOMM_WARN(
2215 "%s: Got UA for dlci=%d in invalid state=%d, flags=%#x\n",
2216 __func__, dlci, pcb->state, pcb->flags);
2221 mtx_unlock(&pcb->pcb_mtx);
2223 NG_BTSOCKET_RFCOMM_WARN(
2224 "%s: Got UA for non-existing dlci=%d\n", __func__, dlci);
2226 error = ng_btsocket_rfcomm_send_command(s,RFCOMM_FRAME_DM,dlci);
2230 } /* ng_btsocket_rfcomm_receive_ua */
2233 * Process RFCOMM DM frame
2237 ng_btsocket_rfcomm_receive_dm(ng_btsocket_rfcomm_session_p s, int dlci)
2239 ng_btsocket_rfcomm_pcb_p pcb = NULL;
2242 mtx_assert(&s->session_mtx, MA_OWNED);
2244 NG_BTSOCKET_RFCOMM_INFO(
2245 "%s: Got DM, session state=%d, flags=%#x, mtu=%d, dlci=%d\n",
2246 __func__, s->state, s->flags, s->mtu, dlci);
2248 /* DLCI == 0 means multiplexor channel */
2250 /* Disconnect all dlc's on the session */
2251 s->state = NG_BTSOCKET_RFCOMM_SESSION_CLOSED;
2252 ng_btsocket_rfcomm_session_clean(s);
2254 pcb = ng_btsocket_rfcomm_pcb_by_dlci(s, dlci);
2256 mtx_lock(&pcb->pcb_mtx);
2258 NG_BTSOCKET_RFCOMM_INFO(
2259 "%s: Got DM for dlci=%d, state=%d, flags=%#x\n",
2260 __func__, dlci, pcb->state, pcb->flags);
2262 if (pcb->state == NG_BTSOCKET_RFCOMM_DLC_CONNECTED)
2265 error = ECONNREFUSED;
2267 ng_btsocket_rfcomm_pcb_kill(pcb, error);
2269 mtx_unlock(&pcb->pcb_mtx);
2271 NG_BTSOCKET_RFCOMM_WARN(
2272 "%s: Got DM for non-existing dlci=%d\n", __func__, dlci);
2276 } /* ng_btsocket_rfcomm_receive_dm */
2279 * Process RFCOMM UIH frame (data)
2283 ng_btsocket_rfcomm_receive_uih(ng_btsocket_rfcomm_session_p s, int dlci,
2284 int pf, struct mbuf *m0)
2286 ng_btsocket_rfcomm_pcb_p pcb = NULL;
2289 mtx_assert(&s->session_mtx, MA_OWNED);
2291 NG_BTSOCKET_RFCOMM_INFO(
2292 "%s: Got UIH, session state=%d, flags=%#x, mtu=%d, dlci=%d, pf=%d, len=%d\n",
2293 __func__, s->state, s->flags, s->mtu, dlci, pf,
2296 /* XXX should we do it here? Check for session flow control */
2297 if (s->flags & NG_BTSOCKET_RFCOMM_SESSION_LFC) {
2298 NG_BTSOCKET_RFCOMM_WARN(
2299 "%s: Got UIH with session flow control asserted, state=%d, flags=%#x\n",
2300 __func__, s->state, s->flags);
2304 /* Check if we have this dlci */
2305 pcb = ng_btsocket_rfcomm_pcb_by_dlci(s, dlci);
2307 NG_BTSOCKET_RFCOMM_WARN(
2308 "%s: Got UIH for non-existing dlci=%d\n", __func__, dlci);
2309 error = ng_btsocket_rfcomm_send_command(s,RFCOMM_FRAME_DM,dlci);
2313 mtx_lock(&pcb->pcb_mtx);
2315 /* Check dlci state */
2316 if (pcb->state != NG_BTSOCKET_RFCOMM_DLC_CONNECTED) {
2317 NG_BTSOCKET_RFCOMM_WARN(
2318 "%s: Got UIH for dlci=%d in invalid state=%d, flags=%#x\n",
2319 __func__, dlci, pcb->state, pcb->flags);
2324 /* Check dlci flow control */
2325 if (((pcb->flags & NG_BTSOCKET_RFCOMM_DLC_CFC) && pcb->rx_cred <= 0) ||
2326 (pcb->lmodem & RFCOMM_MODEM_FC)) {
2327 NG_BTSOCKET_RFCOMM_ERR(
2328 "%s: Got UIH for dlci=%d with asserted flow control, state=%d, " \
2329 "flags=%#x, rx_cred=%d, lmodem=%#x\n",
2330 __func__, dlci, pcb->state, pcb->flags,
2331 pcb->rx_cred, pcb->lmodem);
2335 /* Did we get any credits? */
2336 if ((pcb->flags & NG_BTSOCKET_RFCOMM_DLC_CFC) && pf) {
2337 NG_BTSOCKET_RFCOMM_INFO(
2338 "%s: Got %d more credits for dlci=%d, state=%d, flags=%#x, " \
2339 "rx_cred=%d, tx_cred=%d\n",
2340 __func__, *mtod(m0, u_int8_t *), dlci, pcb->state,
2341 pcb->flags, pcb->rx_cred, pcb->tx_cred);
2343 pcb->tx_cred += *mtod(m0, u_int8_t *);
2346 /* Send more from the DLC. XXX check for errors? */
2347 ng_btsocket_rfcomm_pcb_send(pcb, ALOT);
2350 /* OK the of the rest of the mbuf is the data */
2351 if (m0->m_pkthdr.len > 0) {
2352 /* If we are using credit flow control decrease rx_cred here */
2353 if (pcb->flags & NG_BTSOCKET_RFCOMM_DLC_CFC) {
2354 /* Give remote peer more credits (if needed) */
2355 if (-- pcb->rx_cred <= RFCOMM_MAX_CREDITS / 2)
2356 ng_btsocket_rfcomm_send_credits(pcb);
2358 NG_BTSOCKET_RFCOMM_INFO(
2359 "%s: Remote side still has credits, dlci=%d, state=%d, flags=%#x, " \
2360 "rx_cred=%d, tx_cred=%d\n", __func__, dlci, pcb->state, pcb->flags,
2361 pcb->rx_cred, pcb->tx_cred);
2364 /* Check packet against mtu on dlci */
2365 if (m0->m_pkthdr.len > pcb->mtu) {
2366 NG_BTSOCKET_RFCOMM_ERR(
2367 "%s: Got oversized UIH for dlci=%d, state=%d, flags=%#x, mtu=%d, len=%d\n",
2368 __func__, dlci, pcb->state, pcb->flags,
2369 pcb->mtu, m0->m_pkthdr.len);
2372 } else if (m0->m_pkthdr.len > sbspace(&pcb->so->so_rcv)) {
2375 * This is really bad. Receive queue on socket does
2376 * not have enough space for the packet. We do not
2377 * have any other choice but drop the packet.
2380 NG_BTSOCKET_RFCOMM_ERR(
2381 "%s: Not enough space in socket receive queue. Dropping UIH for dlci=%d, " \
2382 "state=%d, flags=%#x, len=%d, space=%ld\n",
2383 __func__, dlci, pcb->state, pcb->flags,
2384 m0->m_pkthdr.len, sbspace(&pcb->so->so_rcv));
2388 /* Append packet to the socket receive queue */
2389 sbappend(&pcb->so->so_rcv, m0);
2396 mtx_unlock(&pcb->pcb_mtx);
2398 NG_FREE_M(m0); /* checks for != NULL */
2401 } /* ng_btsocket_rfcomm_receive_uih */
2404 * Process RFCOMM MCC command (Multiplexor)
2406 * From TS 07.10 spec
2408 * "5.4.3.1 Information Data
2410 * ...The frames (UIH) sent by the initiating station have the C/R bit set
2411 * to 1 and those sent by the responding station have the C/R bit set to 0..."
2413 * "5.4.6.2 Operating procedures
2415 * Messages always exist in pairs; a command message and a corresponding
2416 * response message. If the C/R bit is set to 1 the message is a command,
2417 * if it is set to 0 the message is a response...
2421 * NOTE: Notice that when UIH frames are used to convey information on DLCI 0
2422 * there are at least two different fields that contain a C/R bit, and the
2423 * bits are set of different form. The C/R bit in the Type field shall be set
2424 * as it is stated above, while the C/R bit in the Address field (see subclause
2425 * 5.2.1.2) shall be set as it is described in subclause 5.4.3.1."
2429 ng_btsocket_rfcomm_receive_mcc(ng_btsocket_rfcomm_session_p s, struct mbuf *m0)
2431 struct rfcomm_mcc_hdr *hdr = NULL;
2432 u_int8_t cr, type, length;
2434 mtx_assert(&s->session_mtx, MA_OWNED);
2437 * We can access data directly in the first mbuf, because we have
2438 * m_pullup()'ed mbuf chain in ng_btsocket_rfcomm_receive_frame().
2439 * All MCC commands should fit into single mbuf (except probably TEST).
2442 hdr = mtod(m0, struct rfcomm_mcc_hdr *);
2443 cr = RFCOMM_CR(hdr->type);
2444 type = RFCOMM_MCC_TYPE(hdr->type);
2445 length = RFCOMM_MCC_LENGTH(hdr->length);
2447 /* Check MCC frame length */
2448 if (sizeof(*hdr) + length != m0->m_pkthdr.len) {
2449 NG_BTSOCKET_RFCOMM_ERR(
2450 "%s: Invalid MCC frame length=%d, len=%d\n",
2451 __func__, length, m0->m_pkthdr.len);
2458 case RFCOMM_MCC_TEST:
2459 return (ng_btsocket_rfcomm_receive_test(s, m0));
2462 case RFCOMM_MCC_FCON:
2463 case RFCOMM_MCC_FCOFF:
2464 return (ng_btsocket_rfcomm_receive_fc(s, m0));
2467 case RFCOMM_MCC_MSC:
2468 return (ng_btsocket_rfcomm_receive_msc(s, m0));
2471 case RFCOMM_MCC_RPN:
2472 return (ng_btsocket_rfcomm_receive_rpn(s, m0));
2475 case RFCOMM_MCC_RLS:
2476 return (ng_btsocket_rfcomm_receive_rls(s, m0));
2480 return (ng_btsocket_rfcomm_receive_pn(s, m0));
2483 case RFCOMM_MCC_NSC:
2484 NG_BTSOCKET_RFCOMM_ERR(
2485 "%s: Got MCC NSC, type=%#x, cr=%d, length=%d, session state=%d, flags=%#x, " \
2486 "mtu=%d, len=%d\n", __func__, RFCOMM_MCC_TYPE(*((u_int8_t *)(hdr + 1))), cr,
2487 length, s->state, s->flags, s->mtu, m0->m_pkthdr.len);
2492 NG_BTSOCKET_RFCOMM_ERR(
2493 "%s: Got unknown MCC, type=%#x, cr=%d, length=%d, session state=%d, " \
2494 "flags=%#x, mtu=%d, len=%d\n",
2495 __func__, type, cr, length, s->state, s->flags,
2496 s->mtu, m0->m_pkthdr.len);
2498 /* Reuse mbuf to send NSC */
2499 hdr = mtod(m0, struct rfcomm_mcc_hdr *);
2500 m0->m_pkthdr.len = m0->m_len = sizeof(*hdr);
2502 /* Create MCC NSC header */
2503 hdr->type = RFCOMM_MKMCC_TYPE(0, RFCOMM_MCC_NSC);
2504 hdr->length = RFCOMM_MKLEN8(1);
2506 /* Put back MCC command type we did not like */
2507 m0->m_data[m0->m_len] = RFCOMM_MKMCC_TYPE(cr, type);
2508 m0->m_pkthdr.len ++;
2511 /* Send UIH frame */
2512 return (ng_btsocket_rfcomm_send_uih(s,
2513 RFCOMM_MKADDRESS(INITIATOR(s), 0), 0, 0, m0));
2518 } /* ng_btsocket_rfcomm_receive_mcc */
2521 * Receive RFCOMM TEST MCC command
2525 ng_btsocket_rfcomm_receive_test(ng_btsocket_rfcomm_session_p s, struct mbuf *m0)
2527 struct rfcomm_mcc_hdr *hdr = mtod(m0, struct rfcomm_mcc_hdr *);
2530 mtx_assert(&s->session_mtx, MA_OWNED);
2532 NG_BTSOCKET_RFCOMM_INFO(
2533 "%s: Got MCC TEST, cr=%d, length=%d, session state=%d, flags=%#x, mtu=%d, " \
2534 "len=%d\n", __func__, RFCOMM_CR(hdr->type), RFCOMM_MCC_LENGTH(hdr->length),
2535 s->state, s->flags, s->mtu, m0->m_pkthdr.len);
2537 if (RFCOMM_CR(hdr->type)) {
2538 hdr->type = RFCOMM_MKMCC_TYPE(0, RFCOMM_MCC_TEST);
2539 error = ng_btsocket_rfcomm_send_uih(s,
2540 RFCOMM_MKADDRESS(INITIATOR(s), 0), 0, 0, m0);
2542 NG_FREE_M(m0); /* XXX ignore response */
2545 } /* ng_btsocket_rfcomm_receive_test */
2548 * Receive RFCOMM FCON/FCOFF MCC command
2552 ng_btsocket_rfcomm_receive_fc(ng_btsocket_rfcomm_session_p s, struct mbuf *m0)
2554 struct rfcomm_mcc_hdr *hdr = mtod(m0, struct rfcomm_mcc_hdr *);
2555 u_int8_t type = RFCOMM_MCC_TYPE(hdr->type);
2558 mtx_assert(&s->session_mtx, MA_OWNED);
2561 * Turn ON/OFF aggregate flow on the entire session. When remote peer
2562 * asserted flow control no transmission shall occur except on dlci 0
2563 * (control channel).
2566 NG_BTSOCKET_RFCOMM_INFO(
2567 "%s: Got MCC FC%s, cr=%d, length=%d, session state=%d, flags=%#x, mtu=%d, " \
2568 "len=%d\n", __func__, (type == RFCOMM_MCC_FCON)? "ON" : "OFF",
2569 RFCOMM_CR(hdr->type), RFCOMM_MCC_LENGTH(hdr->length),
2570 s->state, s->flags, s->mtu, m0->m_pkthdr.len);
2572 if (RFCOMM_CR(hdr->type)) {
2573 if (type == RFCOMM_MCC_FCON)
2574 s->flags &= ~NG_BTSOCKET_RFCOMM_SESSION_RFC;
2576 s->flags |= NG_BTSOCKET_RFCOMM_SESSION_RFC;
2578 hdr->type = RFCOMM_MKMCC_TYPE(0, type);
2579 error = ng_btsocket_rfcomm_send_uih(s,
2580 RFCOMM_MKADDRESS(INITIATOR(s), 0), 0, 0, m0);
2582 NG_FREE_M(m0); /* XXX ignore response */
2585 } /* ng_btsocket_rfcomm_receive_fc */
2588 * Receive RFCOMM MSC MCC command
2592 ng_btsocket_rfcomm_receive_msc(ng_btsocket_rfcomm_session_p s, struct mbuf *m0)
2594 struct rfcomm_mcc_hdr *hdr = mtod(m0, struct rfcomm_mcc_hdr*);
2595 struct rfcomm_mcc_msc *msc = (struct rfcomm_mcc_msc *)(hdr+1);
2596 ng_btsocket_rfcomm_pcb_t *pcb = NULL;
2599 mtx_assert(&s->session_mtx, MA_OWNED);
2601 NG_BTSOCKET_RFCOMM_INFO(
2602 "%s: Got MCC MSC, dlci=%d, cr=%d, length=%d, session state=%d, flags=%#x, " \
2604 __func__, RFCOMM_DLCI(msc->address), RFCOMM_CR(hdr->type),
2605 RFCOMM_MCC_LENGTH(hdr->length), s->state, s->flags,
2606 s->mtu, m0->m_pkthdr.len);
2608 if (RFCOMM_CR(hdr->type)) {
2609 pcb = ng_btsocket_rfcomm_pcb_by_dlci(s, RFCOMM_DLCI(msc->address));
2611 NG_BTSOCKET_RFCOMM_WARN(
2612 "%s: Got MSC command for non-existing dlci=%d\n",
2613 __func__, RFCOMM_DLCI(msc->address));
2619 mtx_lock(&pcb->pcb_mtx);
2621 if (pcb->state != NG_BTSOCKET_RFCOMM_DLC_CONNECTING &&
2622 pcb->state != NG_BTSOCKET_RFCOMM_DLC_CONNECTED) {
2623 NG_BTSOCKET_RFCOMM_WARN(
2624 "%s: Got MSC on dlci=%d in invalid state=%d\n",
2625 __func__, RFCOMM_DLCI(msc->address),
2628 mtx_unlock(&pcb->pcb_mtx);
2634 pcb->rmodem = msc->modem; /* Update remote port signals */
2636 hdr->type = RFCOMM_MKMCC_TYPE(0, RFCOMM_MCC_MSC);
2637 error = ng_btsocket_rfcomm_send_uih(s,
2638 RFCOMM_MKADDRESS(INITIATOR(s), 0), 0, 0, m0);
2641 /* Send more data from DLC. XXX check for errors? */
2642 if (!(pcb->rmodem & RFCOMM_MODEM_FC) &&
2643 !(pcb->flags & NG_BTSOCKET_RFCOMM_DLC_CFC))
2644 ng_btsocket_rfcomm_pcb_send(pcb, ALOT);
2647 mtx_unlock(&pcb->pcb_mtx);
2649 NG_FREE_M(m0); /* XXX ignore response */
2652 } /* ng_btsocket_rfcomm_receive_msc */
2655 * Receive RFCOMM RPN MCC command
2656 * XXX FIXME do we need htole16/le16toh for RPN param_mask?
2660 ng_btsocket_rfcomm_receive_rpn(ng_btsocket_rfcomm_session_p s, struct mbuf *m0)
2662 struct rfcomm_mcc_hdr *hdr = mtod(m0, struct rfcomm_mcc_hdr *);
2663 struct rfcomm_mcc_rpn *rpn = (struct rfcomm_mcc_rpn *)(hdr + 1);
2665 u_int16_t param_mask;
2666 u_int8_t bit_rate, data_bits, stop_bits, parity,
2667 flow_control, xon_char, xoff_char;
2669 mtx_assert(&s->session_mtx, MA_OWNED);
2671 NG_BTSOCKET_RFCOMM_INFO(
2672 "%s: Got MCC RPN, dlci=%d, cr=%d, length=%d, session state=%d, flags=%#x, " \
2674 __func__, RFCOMM_DLCI(rpn->dlci), RFCOMM_CR(hdr->type),
2675 RFCOMM_MCC_LENGTH(hdr->length), s->state, s->flags,
2676 s->mtu, m0->m_pkthdr.len);
2678 if (RFCOMM_CR(hdr->type)) {
2679 param_mask = RFCOMM_RPN_PM_ALL;
2681 if (RFCOMM_MCC_LENGTH(hdr->length) == 1) {
2682 /* Request - return default setting */
2683 bit_rate = RFCOMM_RPN_BR_115200;
2684 data_bits = RFCOMM_RPN_DATA_8;
2685 stop_bits = RFCOMM_RPN_STOP_1;
2686 parity = RFCOMM_RPN_PARITY_NONE;
2687 flow_control = RFCOMM_RPN_FLOW_NONE;
2688 xon_char = RFCOMM_RPN_XON_CHAR;
2689 xoff_char = RFCOMM_RPN_XOFF_CHAR;
2692 * Ignore/accept bit_rate, 8 bits, 1 stop bit, no
2693 * parity, no flow control lines, default XON/XOFF
2697 bit_rate = rpn->bit_rate;
2698 rpn->param_mask = le16toh(rpn->param_mask); /* XXX */
2700 data_bits = RFCOMM_RPN_DATA_BITS(rpn->line_settings);
2701 if (rpn->param_mask & RFCOMM_RPN_PM_DATA &&
2702 data_bits != RFCOMM_RPN_DATA_8) {
2703 data_bits = RFCOMM_RPN_DATA_8;
2704 param_mask ^= RFCOMM_RPN_PM_DATA;
2707 stop_bits = RFCOMM_RPN_STOP_BITS(rpn->line_settings);
2708 if (rpn->param_mask & RFCOMM_RPN_PM_STOP &&
2709 stop_bits != RFCOMM_RPN_STOP_1) {
2710 stop_bits = RFCOMM_RPN_STOP_1;
2711 param_mask ^= RFCOMM_RPN_PM_STOP;
2714 parity = RFCOMM_RPN_PARITY(rpn->line_settings);
2715 if (rpn->param_mask & RFCOMM_RPN_PM_PARITY &&
2716 parity != RFCOMM_RPN_PARITY_NONE) {
2717 parity = RFCOMM_RPN_PARITY_NONE;
2718 param_mask ^= RFCOMM_RPN_PM_PARITY;
2721 flow_control = rpn->flow_control;
2722 if (rpn->param_mask & RFCOMM_RPN_PM_FLOW &&
2723 flow_control != RFCOMM_RPN_FLOW_NONE) {
2724 flow_control = RFCOMM_RPN_FLOW_NONE;
2725 param_mask ^= RFCOMM_RPN_PM_FLOW;
2728 xon_char = rpn->xon_char;
2729 if (rpn->param_mask & RFCOMM_RPN_PM_XON &&
2730 xon_char != RFCOMM_RPN_XON_CHAR) {
2731 xon_char = RFCOMM_RPN_XON_CHAR;
2732 param_mask ^= RFCOMM_RPN_PM_XON;
2735 xoff_char = rpn->xoff_char;
2736 if (rpn->param_mask & RFCOMM_RPN_PM_XOFF &&
2737 xoff_char != RFCOMM_RPN_XOFF_CHAR) {
2738 xoff_char = RFCOMM_RPN_XOFF_CHAR;
2739 param_mask ^= RFCOMM_RPN_PM_XOFF;
2743 rpn->bit_rate = bit_rate;
2744 rpn->line_settings = RFCOMM_MKRPN_LINE_SETTINGS(data_bits,
2746 rpn->flow_control = flow_control;
2747 rpn->xon_char = xon_char;
2748 rpn->xoff_char = xoff_char;
2749 rpn->param_mask = htole16(param_mask); /* XXX */
2751 m0->m_pkthdr.len = m0->m_len = sizeof(*hdr) + sizeof(*rpn);
2753 hdr->type = RFCOMM_MKMCC_TYPE(0, RFCOMM_MCC_RPN);
2754 error = ng_btsocket_rfcomm_send_uih(s,
2755 RFCOMM_MKADDRESS(INITIATOR(s), 0), 0, 0, m0);
2757 NG_FREE_M(m0); /* XXX ignore response */
2760 } /* ng_btsocket_rfcomm_receive_rpn */
2763 * Receive RFCOMM RLS MCC command
2767 ng_btsocket_rfcomm_receive_rls(ng_btsocket_rfcomm_session_p s, struct mbuf *m0)
2769 struct rfcomm_mcc_hdr *hdr = mtod(m0, struct rfcomm_mcc_hdr *);
2770 struct rfcomm_mcc_rls *rls = (struct rfcomm_mcc_rls *)(hdr + 1);
2773 mtx_assert(&s->session_mtx, MA_OWNED);
2776 * XXX FIXME Do we have to do anything else here? Remote peer tries to
2777 * tell us something about DLCI. Just report what we have received and
2778 * return back received values as required by TS 07.10 spec.
2781 NG_BTSOCKET_RFCOMM_INFO(
2782 "%s: Got MCC RLS, dlci=%d, status=%#x, cr=%d, length=%d, session state=%d, " \
2783 "flags=%#x, mtu=%d, len=%d\n",
2784 __func__, RFCOMM_DLCI(rls->address), rls->status,
2785 RFCOMM_CR(hdr->type), RFCOMM_MCC_LENGTH(hdr->length),
2786 s->state, s->flags, s->mtu, m0->m_pkthdr.len);
2788 if (RFCOMM_CR(hdr->type)) {
2789 if (rls->status & 0x1)
2790 NG_BTSOCKET_RFCOMM_ERR(
2791 "%s: Got RLS dlci=%d, error=%#x\n", __func__, RFCOMM_DLCI(rls->address),
2794 hdr->type = RFCOMM_MKMCC_TYPE(0, RFCOMM_MCC_RLS);
2795 error = ng_btsocket_rfcomm_send_uih(s,
2796 RFCOMM_MKADDRESS(INITIATOR(s), 0), 0, 0, m0);
2798 NG_FREE_M(m0); /* XXX ignore responses */
2801 } /* ng_btsocket_rfcomm_receive_rls */
2804 * Receive RFCOMM PN MCC command
2808 ng_btsocket_rfcomm_receive_pn(ng_btsocket_rfcomm_session_p s, struct mbuf *m0)
2810 struct rfcomm_mcc_hdr *hdr = mtod(m0, struct rfcomm_mcc_hdr*);
2811 struct rfcomm_mcc_pn *pn = (struct rfcomm_mcc_pn *)(hdr+1);
2812 ng_btsocket_rfcomm_pcb_t *pcb = NULL;
2815 mtx_assert(&s->session_mtx, MA_OWNED);
2817 NG_BTSOCKET_RFCOMM_INFO(
2818 "%s: Got MCC PN, dlci=%d, cr=%d, length=%d, flow_control=%#x, priority=%d, " \
2819 "ack_timer=%d, mtu=%d, max_retrans=%d, credits=%d, session state=%d, " \
2820 "flags=%#x, session mtu=%d, len=%d\n",
2821 __func__, pn->dlci, RFCOMM_CR(hdr->type),
2822 RFCOMM_MCC_LENGTH(hdr->length), pn->flow_control, pn->priority,
2823 pn->ack_timer, le16toh(pn->mtu), pn->max_retrans, pn->credits,
2824 s->state, s->flags, s->mtu, m0->m_pkthdr.len);
2826 if (pn->dlci == 0) {
2827 NG_BTSOCKET_RFCOMM_ERR("%s: Zero dlci in MCC PN\n", __func__);
2833 /* Check if we have this dlci */
2834 pcb = ng_btsocket_rfcomm_pcb_by_dlci(s, pn->dlci);
2836 mtx_lock(&pcb->pcb_mtx);
2838 if (RFCOMM_CR(hdr->type)) {
2840 ng_btsocket_rfcomm_set_pn(pcb, 1, pn->flow_control,
2841 pn->credits, pn->mtu);
2843 if (pcb->flags & NG_BTSOCKET_RFCOMM_DLC_CFC) {
2844 pn->flow_control = 0xe0;
2845 pn->credits = RFCOMM_DEFAULT_CREDITS;
2847 pn->flow_control = 0;
2851 hdr->type = RFCOMM_MKMCC_TYPE(0, RFCOMM_MCC_PN);
2852 error = ng_btsocket_rfcomm_send_uih(s,
2853 RFCOMM_MKADDRESS(INITIATOR(s), 0),
2856 /* PN Response - proceed with SABM. Timeout still set */
2857 if (pcb->state == NG_BTSOCKET_RFCOMM_DLC_CONFIGURING) {
2858 ng_btsocket_rfcomm_set_pn(pcb, 0,
2859 pn->flow_control, pn->credits, pn->mtu);
2861 pcb->state = NG_BTSOCKET_RFCOMM_DLC_CONNECTING;
2862 error = ng_btsocket_rfcomm_send_command(s,
2863 RFCOMM_FRAME_SABM, pn->dlci);
2865 NG_BTSOCKET_RFCOMM_WARN(
2866 "%s: Got PN response for dlci=%d in invalid state=%d\n",
2867 __func__, pn->dlci, pcb->state);
2872 mtx_unlock(&pcb->pcb_mtx);
2873 } else if (RFCOMM_CR(hdr->type)) {
2874 /* PN request to non-existing dlci - incomming connection */
2875 pcb = ng_btsocket_rfcomm_connect_ind(s,
2876 RFCOMM_SRVCHANNEL(pn->dlci));
2878 mtx_lock(&pcb->pcb_mtx);
2880 pcb->dlci = pn->dlci;
2882 ng_btsocket_rfcomm_set_pn(pcb, 1, pn->flow_control,
2883 pn->credits, pn->mtu);
2885 if (pcb->flags & NG_BTSOCKET_RFCOMM_DLC_CFC) {
2886 pn->flow_control = 0xe0;
2887 pn->credits = RFCOMM_DEFAULT_CREDITS;
2889 pn->flow_control = 0;
2893 hdr->type = RFCOMM_MKMCC_TYPE(0, RFCOMM_MCC_PN);
2894 error = ng_btsocket_rfcomm_send_uih(s,
2895 RFCOMM_MKADDRESS(INITIATOR(s), 0),
2899 ng_btsocket_rfcomm_timeout(pcb);
2900 pcb->state = NG_BTSOCKET_RFCOMM_DLC_CONNECTING;
2901 soisconnecting(pcb->so);
2903 ng_btsocket_rfcomm_pcb_kill(pcb, error);
2905 mtx_unlock(&pcb->pcb_mtx);
2907 /* Nobody is listen()ing on this channel */
2908 error = ng_btsocket_rfcomm_send_command(s,
2909 RFCOMM_FRAME_DM, pn->dlci);
2913 NG_FREE_M(m0); /* XXX ignore response to non-existing dlci */
2916 } /* ng_btsocket_rfcomm_receive_pn */
2919 * Set PN parameters for dlci. Caller must hold pcb->pcb_mtx.
2921 * From Bluetooth spec.
2923 * "... The CL1 - CL4 field is completely redefined. (In TS07.10 this defines
2924 * the convergence layer to use, which is not applicable to RFCOMM. In RFCOMM,
2925 * in Bluetooth versions up to 1.0B, this field was forced to 0).
2927 * In the PN request sent prior to a DLC establishment, this field must contain
2928 * the value 15 (0xF), indicating support of credit based flow control in the
2929 * sender. See Table 5.3 below. If the PN response contains any other value
2930 * than 14 (0xE) in this field, it is inferred that the peer RFCOMM entity is
2931 * not supporting the credit based flow control feature. (This is only possible
2932 * if the peer RFCOMM implementation is only conforming to Bluetooth version
2933 * 1.0B.) If a PN request is sent on an already open DLC, then this field must
2934 * contain the value zero; it is not possible to set initial credits more
2935 * than once per DLC activation. A responding implementation must set this
2936 * field in the PN response to 14 (0xE), if (and only if) the value in the PN
2937 * request was 15..."
2941 ng_btsocket_rfcomm_set_pn(ng_btsocket_rfcomm_pcb_p pcb, u_int8_t cr,
2942 u_int8_t flow_control, u_int8_t credits, u_int16_t mtu)
2944 mtx_assert(&pcb->pcb_mtx, MA_OWNED);
2946 pcb->mtu = le16toh(mtu);
2949 if (flow_control == 0xf0) {
2950 pcb->flags |= NG_BTSOCKET_RFCOMM_DLC_CFC;
2951 pcb->tx_cred = credits;
2953 pcb->flags &= ~NG_BTSOCKET_RFCOMM_DLC_CFC;
2957 if (flow_control == 0xe0) {
2958 pcb->flags |= NG_BTSOCKET_RFCOMM_DLC_CFC;
2959 pcb->tx_cred = credits;
2961 pcb->flags &= ~NG_BTSOCKET_RFCOMM_DLC_CFC;
2966 NG_BTSOCKET_RFCOMM_INFO(
2967 "%s: cr=%d, dlci=%d, state=%d, flags=%#x, mtu=%d, rx_cred=%d, tx_cred=%d\n",
2968 __func__, cr, pcb->dlci, pcb->state, pcb->flags, pcb->mtu,
2969 pcb->rx_cred, pcb->tx_cred);
2970 } /* ng_btsocket_rfcomm_set_pn */
2973 * Send RFCOMM SABM/DISC/UA/DM frames. Caller must hold s->session_mtx
2977 ng_btsocket_rfcomm_send_command(ng_btsocket_rfcomm_session_p s,
2978 u_int8_t type, u_int8_t dlci)
2980 struct rfcomm_cmd_hdr *hdr = NULL;
2981 struct mbuf *m = NULL;
2984 mtx_assert(&s->session_mtx, MA_OWNED);
2986 NG_BTSOCKET_RFCOMM_INFO(
2987 "%s: Sending command type %#x, session state=%d, flags=%#x, mtu=%d, dlci=%d\n",
2988 __func__, type, s->state, s->flags, s->mtu, dlci);
2991 case RFCOMM_FRAME_SABM:
2992 case RFCOMM_FRAME_DISC:
2996 case RFCOMM_FRAME_UA:
2997 case RFCOMM_FRAME_DM:
3002 panic("%s: Invalid frame type=%#x\n", __func__, type);
3007 MGETHDR(m, M_DONTWAIT, MT_DATA);
3011 m->m_pkthdr.len = m->m_len = sizeof(*hdr);
3013 hdr = mtod(m, struct rfcomm_cmd_hdr *);
3014 hdr->address = RFCOMM_MKADDRESS(cr, dlci);
3015 hdr->control = RFCOMM_MKCONTROL(type, 1);
3016 hdr->length = RFCOMM_MKLEN8(0);
3017 hdr->fcs = ng_btsocket_rfcomm_fcs3((u_int8_t *) hdr);
3019 NG_BT_MBUFQ_ENQUEUE(&s->outq, m);
3022 } /* ng_btsocket_rfcomm_send_command */
3025 * Send RFCOMM UIH frame. Caller must hold s->session_mtx
3029 ng_btsocket_rfcomm_send_uih(ng_btsocket_rfcomm_session_p s, u_int8_t address,
3030 u_int8_t pf, u_int8_t credits, struct mbuf *data)
3032 struct rfcomm_frame_hdr *hdr = NULL;
3033 struct mbuf *m = NULL, *mcrc = NULL;
3036 mtx_assert(&s->session_mtx, MA_OWNED);
3038 MGETHDR(m, M_DONTWAIT, MT_DATA);
3043 m->m_pkthdr.len = m->m_len = sizeof(*hdr);
3045 MGET(mcrc, M_DONTWAIT, MT_DATA);
3052 /* Fill UIH frame header */
3053 hdr = mtod(m, struct rfcomm_frame_hdr *);
3054 hdr->address = address;
3055 hdr->control = RFCOMM_MKCONTROL(RFCOMM_FRAME_UIH, pf);
3058 mcrc->m_data[0] = ng_btsocket_rfcomm_fcs2((u_int8_t *) hdr);
3060 /* Put length back */
3061 length = (data != NULL)? data->m_pkthdr.len : 0;
3063 u_int16_t l = htole16(RFCOMM_MKLEN16(length));
3065 bcopy(&l, &hdr->length, sizeof(l));
3069 hdr->length = RFCOMM_MKLEN8(length);
3072 m->m_data[m->m_len] = credits;
3080 m->m_pkthdr.len += length;
3087 NG_BTSOCKET_RFCOMM_INFO(
3088 "%s: Sending UIH state=%d, flags=%#x, address=%d, length=%d, pf=%d, " \
3089 "credits=%d, len=%d\n",
3090 __func__, s->state, s->flags, address, length, pf, credits,
3093 NG_BT_MBUFQ_ENQUEUE(&s->outq, m);
3096 } /* ng_btsocket_rfcomm_send_uih */
3099 * Send MSC request. Caller must hold pcb->pcb_mtx and pcb->session->session_mtx
3103 ng_btsocket_rfcomm_send_msc(ng_btsocket_rfcomm_pcb_p pcb)
3105 struct mbuf *m = NULL;
3106 struct rfcomm_mcc_hdr *hdr = NULL;
3107 struct rfcomm_mcc_msc *msc = NULL;
3109 mtx_assert(&pcb->session->session_mtx, MA_OWNED);
3110 mtx_assert(&pcb->pcb_mtx, MA_OWNED);
3112 MGETHDR(m, M_DONTWAIT, MT_DATA);
3116 m->m_pkthdr.len = m->m_len = sizeof(*hdr) + sizeof(*msc);
3118 hdr = mtod(m, struct rfcomm_mcc_hdr *);
3119 msc = (struct rfcomm_mcc_msc *)(hdr + 1);
3121 hdr->type = RFCOMM_MKMCC_TYPE(1, RFCOMM_MCC_MSC);
3122 hdr->length = RFCOMM_MKLEN8(sizeof(*msc));
3124 msc->address = RFCOMM_MKADDRESS(1, pcb->dlci);
3125 msc->modem = pcb->lmodem;
3127 NG_BTSOCKET_RFCOMM_INFO(
3128 "%s: Sending MSC dlci=%d, state=%d, flags=%#x, address=%d, modem=%#x\n",
3129 __func__, pcb->dlci, pcb->state, pcb->flags, msc->address,
3132 return (ng_btsocket_rfcomm_send_uih(pcb->session,
3133 RFCOMM_MKADDRESS(INITIATOR(pcb->session), 0), 0, 0, m));
3134 } /* ng_btsocket_rfcomm_send_msc */
3137 * Send PN request. Caller must hold pcb->pcb_mtx and pcb->session->session_mtx
3141 ng_btsocket_rfcomm_send_pn(ng_btsocket_rfcomm_pcb_p pcb)
3143 struct mbuf *m = NULL;
3144 struct rfcomm_mcc_hdr *hdr = NULL;
3145 struct rfcomm_mcc_pn *pn = NULL;
3147 mtx_assert(&pcb->session->session_mtx, MA_OWNED);
3148 mtx_assert(&pcb->pcb_mtx, MA_OWNED);
3150 MGETHDR(m, M_DONTWAIT, MT_DATA);
3154 m->m_pkthdr.len = m->m_len = sizeof(*hdr) + sizeof(*pn);
3156 hdr = mtod(m, struct rfcomm_mcc_hdr *);
3157 pn = (struct rfcomm_mcc_pn *)(hdr + 1);
3159 hdr->type = RFCOMM_MKMCC_TYPE(1, RFCOMM_MCC_PN);
3160 hdr->length = RFCOMM_MKLEN8(sizeof(*pn));
3162 pn->dlci = pcb->dlci;
3165 * Set default DLCI priority as described in GSM 07.10
3166 * (ETSI TS 101 369) clause 5.6 page 42
3169 pn->priority = (pcb->dlci < 56)? (((pcb->dlci >> 3) << 3) + 7) : 61;
3171 pn->mtu = htole16(pcb->mtu);
3172 pn->max_retrans = 0;
3174 if (pcb->flags & NG_BTSOCKET_RFCOMM_DLC_CFC) {
3175 pn->flow_control = 0xf0;
3176 pn->credits = pcb->rx_cred;
3178 pn->flow_control = 0;
3182 NG_BTSOCKET_RFCOMM_INFO(
3183 "%s: Sending PN dlci=%d, state=%d, flags=%#x, mtu=%d, flow_control=%#x, " \
3184 "credits=%d\n", __func__, pcb->dlci, pcb->state, pcb->flags, pcb->mtu,
3185 pn->flow_control, pn->credits);
3187 return (ng_btsocket_rfcomm_send_uih(pcb->session,
3188 RFCOMM_MKADDRESS(INITIATOR(pcb->session), 0), 0, 0, m));
3189 } /* ng_btsocket_rfcomm_send_pn */
3192 * Calculate and send credits based on available space in receive buffer
3196 ng_btsocket_rfcomm_send_credits(ng_btsocket_rfcomm_pcb_p pcb)
3201 mtx_assert(&pcb->pcb_mtx, MA_OWNED);
3202 mtx_assert(&pcb->session->session_mtx, MA_OWNED);
3204 NG_BTSOCKET_RFCOMM_INFO(
3205 "%s: Sending more credits, dlci=%d, state=%d, flags=%#x, mtu=%d, " \
3206 "space=%ld, tx_cred=%d, rx_cred=%d\n",
3207 __func__, pcb->dlci, pcb->state, pcb->flags, pcb->mtu,
3208 sbspace(&pcb->so->so_rcv), pcb->tx_cred, pcb->rx_cred);
3210 credits = sbspace(&pcb->so->so_rcv) / pcb->mtu;
3212 if (pcb->rx_cred + credits > RFCOMM_MAX_CREDITS)
3213 credits = RFCOMM_MAX_CREDITS - pcb->rx_cred;
3215 error = ng_btsocket_rfcomm_send_uih(
3217 RFCOMM_MKADDRESS(INITIATOR(pcb->session),
3218 pcb->dlci), 1, credits, NULL);
3220 pcb->rx_cred += credits;
3222 NG_BTSOCKET_RFCOMM_INFO(
3223 "%s: Gave remote side %d more credits, dlci=%d, state=%d, flags=%#x, " \
3224 "rx_cred=%d, tx_cred=%d\n", __func__, credits, pcb->dlci, pcb->state,
3225 pcb->flags, pcb->rx_cred, pcb->tx_cred);
3227 NG_BTSOCKET_RFCOMM_ERR(
3228 "%s: Could not send credits, error=%d, dlci=%d, state=%d, flags=%#x, " \
3229 "mtu=%d, space=%ld, tx_cred=%d, rx_cred=%d\n",
3230 __func__, error, pcb->dlci, pcb->state,
3231 pcb->flags, pcb->mtu, sbspace(&pcb->so->so_rcv),
3232 pcb->tx_cred, pcb->rx_cred);
3236 } /* ng_btsocket_rfcomm_send_credits */
3238 /*****************************************************************************
3239 *****************************************************************************
3241 *****************************************************************************
3242 *****************************************************************************/
3245 * Send data from socket send buffer
3246 * Caller must hold pcb->pcb_mtx and pcb->session->session_mtx
3250 ng_btsocket_rfcomm_pcb_send(ng_btsocket_rfcomm_pcb_p pcb, int limit)
3252 struct mbuf *m = NULL;
3253 int sent, length, error;
3255 mtx_assert(&pcb->session->session_mtx, MA_OWNED);
3256 mtx_assert(&pcb->pcb_mtx, MA_OWNED);
3258 if (pcb->flags & NG_BTSOCKET_RFCOMM_DLC_CFC)
3259 limit = min(limit, pcb->tx_cred);
3260 else if (!(pcb->rmodem & RFCOMM_MODEM_FC))
3261 limit = min(limit, RFCOMM_MAX_CREDITS); /* XXX ??? */
3266 NG_BTSOCKET_RFCOMM_INFO(
3267 "%s: Could not send - remote flow control asserted, dlci=%d, flags=%#x, " \
3268 "rmodem=%#x, tx_cred=%d\n",
3269 __func__, pcb->dlci, pcb->flags, pcb->rmodem,
3275 for (error = 0, sent = 0; sent < limit; sent ++) {
3276 length = min(pcb->mtu, pcb->so->so_snd.sb_cc);
3280 /* Get the chunk from the socket's send buffer */
3281 m = ng_btsocket_rfcomm_prepare_packet(&pcb->so->so_snd, length);
3287 sbdrop(&pcb->so->so_snd, length);
3289 error = ng_btsocket_rfcomm_send_uih(pcb->session,
3290 RFCOMM_MKADDRESS(INITIATOR(pcb->session),
3291 pcb->dlci), 0, 0, m);
3296 if (pcb->flags & NG_BTSOCKET_RFCOMM_DLC_CFC)
3297 pcb->tx_cred -= sent;
3299 if (error == 0 && sent > 0) {
3300 pcb->flags &= ~NG_BTSOCKET_RFCOMM_DLC_SENDING;
3305 } /* ng_btsocket_rfcomm_pcb_send */
3308 * Unlink and disconnect DLC. If ng_btsocket_rfcomm_pcb_kill() returns
3309 * non zero value than socket has no reference and has to be detached.
3310 * Caller must hold pcb->pcb_mtx and pcb->session->session_mtx
3314 ng_btsocket_rfcomm_pcb_kill(ng_btsocket_rfcomm_pcb_p pcb, int error)
3316 ng_btsocket_rfcomm_session_p s = pcb->session;
3318 NG_BTSOCKET_RFCOMM_INFO(
3319 "%s: Killing DLC, so=%p, dlci=%d, state=%d, flags=%#x, error=%d\n",
3320 __func__, pcb->so, pcb->dlci, pcb->state, pcb->flags, error);
3322 if (pcb->session == NULL)
3323 panic("%s: DLC without session, pcb=%p, state=%d, flags=%#x\n",
3324 __func__, pcb, pcb->state, pcb->flags);
3326 mtx_assert(&pcb->session->session_mtx, MA_OWNED);
3327 mtx_assert(&pcb->pcb_mtx, MA_OWNED);
3329 if (pcb->flags & NG_BTSOCKET_RFCOMM_DLC_TIMO)
3330 ng_btsocket_rfcomm_untimeout(pcb);
3332 /* Detach DLC from the session. Does not matter which state DLC in */
3333 LIST_REMOVE(pcb, session_next);
3334 pcb->session = NULL;
3336 /* Change DLC state and wakeup all sleepers */
3337 pcb->state = NG_BTSOCKET_RFCOMM_DLC_CLOSED;
3338 pcb->so->so_error = error;
3339 soisdisconnected(pcb->so);
3340 wakeup(&pcb->state);
3342 /* Check if we have any DLCs left on the session */
3343 if (LIST_EMPTY(&s->dlcs) && INITIATOR(s)) {
3344 NG_BTSOCKET_RFCOMM_INFO(
3345 "%s: Disconnecting session, state=%d, flags=%#x, mtu=%d\n",
3346 __func__, s->state, s->flags, s->mtu);
3349 case NG_BTSOCKET_RFCOMM_SESSION_CLOSED:
3350 case NG_BTSOCKET_RFCOMM_SESSION_DISCONNECTING:
3352 * Do not have to do anything here. We can get here
3353 * when L2CAP connection was terminated or we have
3354 * received DISC on multiplexor channel
3358 case NG_BTSOCKET_RFCOMM_SESSION_OPEN:
3359 /* Send DISC on multiplexor channel */
3360 error = ng_btsocket_rfcomm_send_command(s,
3361 RFCOMM_FRAME_DISC, 0);
3363 s->state = NG_BTSOCKET_RFCOMM_SESSION_DISCONNECTING;
3368 case NG_BTSOCKET_RFCOMM_SESSION_CONNECTING:
3369 case NG_BTSOCKET_RFCOMM_SESSION_CONNECTED:
3370 s->state = NG_BTSOCKET_RFCOMM_SESSION_CLOSED;
3373 /* case NG_BTSOCKET_RFCOMM_SESSION_LISTENING: */
3375 panic("%s: Invalid session state=%d, flags=%#x\n",
3376 __func__, s->state, s->flags);
3380 ng_btsocket_rfcomm_task_wakeup();
3382 } /* ng_btsocket_rfcomm_pcb_kill */
3385 * Look for given dlci for given RFCOMM session. Caller must hold s->session_mtx
3388 static ng_btsocket_rfcomm_pcb_p
3389 ng_btsocket_rfcomm_pcb_by_dlci(ng_btsocket_rfcomm_session_p s, int dlci)
3391 ng_btsocket_rfcomm_pcb_p pcb = NULL;
3393 mtx_assert(&s->session_mtx, MA_OWNED);
3395 LIST_FOREACH(pcb, &s->dlcs, session_next)
3396 if (pcb->dlci == dlci)
3400 } /* ng_btsocket_rfcomm_pcb_by_dlci */
3403 * Look for socket that listens on given src address and given channel
3406 static ng_btsocket_rfcomm_pcb_p
3407 ng_btsocket_rfcomm_pcb_listener(bdaddr_p src, int channel)
3409 ng_btsocket_rfcomm_pcb_p pcb = NULL, pcb1 = NULL;
3411 mtx_lock(&ng_btsocket_rfcomm_sockets_mtx);
3413 LIST_FOREACH(pcb, &ng_btsocket_rfcomm_sockets, next) {
3414 if (pcb->channel != channel ||
3415 !(pcb->so->so_options & SO_ACCEPTCONN))
3418 if (bcmp(&pcb->src, src, sizeof(*src)) == 0)
3421 if (bcmp(&pcb->src, NG_HCI_BDADDR_ANY, sizeof(bdaddr_t)) == 0)
3425 mtx_unlock(&ng_btsocket_rfcomm_sockets_mtx);
3427 return ((pcb != NULL)? pcb : pcb1);
3428 } /* ng_btsocket_rfcomm_pcb_listener */
3430 /*****************************************************************************
3431 *****************************************************************************
3433 *****************************************************************************
3434 *****************************************************************************/
3437 * Set timeout. Caller MUST hold pcb_mtx
3441 ng_btsocket_rfcomm_timeout(ng_btsocket_rfcomm_pcb_p pcb)
3443 mtx_assert(&pcb->pcb_mtx, MA_OWNED);
3445 if (!(pcb->flags & NG_BTSOCKET_RFCOMM_DLC_TIMO)) {
3446 pcb->flags |= NG_BTSOCKET_RFCOMM_DLC_TIMO;
3447 pcb->flags &= ~NG_BTSOCKET_RFCOMM_DLC_TIMEDOUT;
3448 pcb->timo = timeout(ng_btsocket_rfcomm_process_timeout, pcb,
3449 ng_btsocket_rfcomm_timo * hz);
3451 panic("%s: Duplicated socket timeout?!\n", __func__);
3452 } /* ng_btsocket_rfcomm_timeout */
3455 * Unset pcb timeout. Caller MUST hold pcb_mtx
3459 ng_btsocket_rfcomm_untimeout(ng_btsocket_rfcomm_pcb_p pcb)
3461 mtx_assert(&pcb->pcb_mtx, MA_OWNED);
3463 if (pcb->flags & NG_BTSOCKET_RFCOMM_DLC_TIMO) {
3464 untimeout(ng_btsocket_rfcomm_process_timeout, pcb, pcb->timo);
3465 pcb->flags &= ~NG_BTSOCKET_RFCOMM_DLC_TIMO;
3466 pcb->flags &= ~NG_BTSOCKET_RFCOMM_DLC_TIMEDOUT;
3468 panic("%s: No socket timeout?!\n", __func__);
3469 } /* ng_btsocket_rfcomm_timeout */
3472 * Process pcb timeout
3476 ng_btsocket_rfcomm_process_timeout(void *xpcb)
3478 ng_btsocket_rfcomm_pcb_p pcb = (ng_btsocket_rfcomm_pcb_p) xpcb;
3480 mtx_lock(&pcb->pcb_mtx);
3482 NG_BTSOCKET_RFCOMM_INFO(
3483 "%s: Timeout, so=%p, dlci=%d, state=%d, flags=%#x\n",
3484 __func__, pcb->so, pcb->dlci, pcb->state, pcb->flags);
3486 pcb->flags &= ~NG_BTSOCKET_RFCOMM_DLC_TIMO;
3487 pcb->flags |= NG_BTSOCKET_RFCOMM_DLC_TIMEDOUT;
3489 switch (pcb->state) {
3490 case NG_BTSOCKET_RFCOMM_DLC_CONFIGURING:
3491 case NG_BTSOCKET_RFCOMM_DLC_CONNECTING:
3492 pcb->state = NG_BTSOCKET_RFCOMM_DLC_DISCONNECTING;
3495 case NG_BTSOCKET_RFCOMM_DLC_W4_CONNECT:
3496 case NG_BTSOCKET_RFCOMM_DLC_DISCONNECTING:
3501 "%s: DLC timeout in invalid state, dlci=%d, state=%d, flags=%#x\n",
3502 __func__, pcb->dlci, pcb->state, pcb->flags);
3506 ng_btsocket_rfcomm_task_wakeup();
3508 mtx_unlock(&pcb->pcb_mtx);
3509 } /* ng_btsocket_rfcomm_process_timeout */
3512 * Get up to length bytes from the socket buffer
3515 static struct mbuf *
3516 ng_btsocket_rfcomm_prepare_packet(struct sockbuf *sb, int length)
3518 struct mbuf *top = NULL, *m = NULL, *n = NULL, *nextpkt = NULL;
3519 int mlen, noff, len;
3521 MGETHDR(top, M_DONTWAIT, MT_DATA);
3525 top->m_pkthdr.len = length;
3531 nextpkt = n->m_nextpkt;
3534 while (length > 0 && n != NULL) {
3535 len = min(mlen - m->m_len, n->m_len - noff);
3539 bcopy(mtod(n, caddr_t)+noff, mtod(m, caddr_t)+m->m_len, len);
3544 if (length > 0 && m->m_len == mlen) {
3545 MGET(m->m_next, M_DONTWAIT, MT_DATA);
3546 if (m->m_next == NULL) {
3556 if (noff == n->m_len) {
3563 nextpkt = (n != NULL)? n->m_nextpkt : NULL;
3568 panic("%s: length=%d\n", __func__, length);
3569 if (length > 0 && n == NULL)
3570 panic("%s: bogus length=%d, n=%p\n", __func__, length, n);
3573 } /* ng_btsocket_rfcomm_prepare_packet */