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 int ng_btsocket_rfcomm_upcall
97 (struct socket *so, void *arg, int waitflag);
98 static void ng_btsocket_rfcomm_sessions_task
99 (void *ctx, int pending);
100 static void ng_btsocket_rfcomm_session_task
101 (ng_btsocket_rfcomm_session_p s);
102 #define ng_btsocket_rfcomm_task_wakeup() \
103 taskqueue_enqueue(taskqueue_swi_giant, &ng_btsocket_rfcomm_task)
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 pcb = malloc(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);
1022 } /* ng_btsocket_rfcomm_upcall */
1025 * RFCOMM task. Will handle all RFCOMM sessions in one pass.
1026 * XXX FIXME does not scale very well
1030 ng_btsocket_rfcomm_sessions_task(void *ctx, int pending)
1032 ng_btsocket_rfcomm_session_p s = NULL, s_next = NULL;
1034 mtx_lock(&ng_btsocket_rfcomm_sessions_mtx);
1036 for (s = LIST_FIRST(&ng_btsocket_rfcomm_sessions); s != NULL; ) {
1037 mtx_lock(&s->session_mtx);
1038 s_next = LIST_NEXT(s, next);
1040 ng_btsocket_rfcomm_session_task(s);
1042 if (s->state == NG_BTSOCKET_RFCOMM_SESSION_CLOSED) {
1043 /* Unlink and clean the session */
1044 LIST_REMOVE(s, next);
1046 NG_BT_MBUFQ_DRAIN(&s->outq);
1047 if (!LIST_EMPTY(&s->dlcs))
1048 panic("%s: DLC list is not empty\n", __func__);
1050 /* Close L2CAP socket */
1051 SOCKBUF_LOCK(&s->l2so->so_rcv);
1052 soupcall_clear(s->l2so, SO_RCV);
1053 SOCKBUF_UNLOCK(&s->l2so->so_rcv);
1054 SOCKBUF_LOCK(&s->l2so->so_snd);
1055 soupcall_clear(s->l2so, SO_SND);
1056 SOCKBUF_UNLOCK(&s->l2so->so_snd);
1059 mtx_unlock(&s->session_mtx);
1061 mtx_destroy(&s->session_mtx);
1062 bzero(s, sizeof(*s));
1063 free(s, M_NETGRAPH_BTSOCKET_RFCOMM);
1065 mtx_unlock(&s->session_mtx);
1070 mtx_unlock(&ng_btsocket_rfcomm_sessions_mtx);
1071 } /* ng_btsocket_rfcomm_sessions_task */
1074 * Process RFCOMM session. Will handle all RFCOMM sockets in one pass.
1078 ng_btsocket_rfcomm_session_task(ng_btsocket_rfcomm_session_p s)
1080 mtx_assert(&s->session_mtx, MA_OWNED);
1082 if (s->l2so->so_rcv.sb_state & SBS_CANTRCVMORE) {
1083 NG_BTSOCKET_RFCOMM_INFO(
1084 "%s: L2CAP connection has been terminated, so=%p, so_state=%#x, so_count=%d, " \
1085 "state=%d, flags=%#x\n", __func__, s->l2so, s->l2so->so_state,
1086 s->l2so->so_count, s->state, s->flags);
1088 s->state = NG_BTSOCKET_RFCOMM_SESSION_CLOSED;
1089 ng_btsocket_rfcomm_session_clean(s);
1092 /* Now process upcall */
1094 /* Try to accept new L2CAP connection(s) */
1095 case NG_BTSOCKET_RFCOMM_SESSION_LISTENING:
1096 while (ng_btsocket_rfcomm_session_accept(s) == 0)
1100 /* Process the results of the L2CAP connect */
1101 case NG_BTSOCKET_RFCOMM_SESSION_CONNECTING:
1102 ng_btsocket_rfcomm_session_process_pcb(s);
1104 if (ng_btsocket_rfcomm_session_connect(s) != 0) {
1105 s->state = NG_BTSOCKET_RFCOMM_SESSION_CLOSED;
1106 ng_btsocket_rfcomm_session_clean(s);
1110 /* Try to receive/send more data */
1111 case NG_BTSOCKET_RFCOMM_SESSION_CONNECTED:
1112 case NG_BTSOCKET_RFCOMM_SESSION_OPEN:
1113 case NG_BTSOCKET_RFCOMM_SESSION_DISCONNECTING:
1114 ng_btsocket_rfcomm_session_process_pcb(s);
1116 if (ng_btsocket_rfcomm_session_receive(s) != 0) {
1117 s->state = NG_BTSOCKET_RFCOMM_SESSION_CLOSED;
1118 ng_btsocket_rfcomm_session_clean(s);
1119 } else if (ng_btsocket_rfcomm_session_send(s) != 0) {
1120 s->state = NG_BTSOCKET_RFCOMM_SESSION_CLOSED;
1121 ng_btsocket_rfcomm_session_clean(s);
1125 case NG_BTSOCKET_RFCOMM_SESSION_CLOSED:
1129 panic("%s: Invalid session state=%d, flags=%#x\n",
1130 __func__, s->state, s->flags);
1133 } /* ng_btsocket_rfcomm_session_task */
1136 * Process RFCOMM connection indicator. Caller must hold s->session_mtx
1139 static ng_btsocket_rfcomm_pcb_p
1140 ng_btsocket_rfcomm_connect_ind(ng_btsocket_rfcomm_session_p s, int channel)
1142 ng_btsocket_rfcomm_pcb_p pcb = NULL, pcb1 = NULL;
1143 ng_btsocket_l2cap_pcb_p l2pcb = NULL;
1144 struct socket *so1 = NULL;
1146 mtx_assert(&s->session_mtx, MA_OWNED);
1149 * Try to find RFCOMM socket that listens on given source address
1150 * and channel. This will return the best possible match.
1153 l2pcb = so2l2cap_pcb(s->l2so);
1154 pcb = ng_btsocket_rfcomm_pcb_listener(&l2pcb->src, channel);
1159 * Check the pending connections queue and if we have space then
1160 * create new socket and set proper source and destination address,
1164 mtx_lock(&pcb->pcb_mtx);
1166 if (pcb->so->so_qlen <= pcb->so->so_qlimit)
1167 so1 = sonewconn(pcb->so, 0);
1169 mtx_unlock(&pcb->pcb_mtx);
1175 * If we got here than we have created new socket. So complete the
1176 * connection. Set source and destination address from the session.
1179 pcb1 = so2rfcomm_pcb(so1);
1181 panic("%s: pcb1 == NULL\n", __func__);
1183 mtx_lock(&pcb1->pcb_mtx);
1185 bcopy(&l2pcb->src, &pcb1->src, sizeof(pcb1->src));
1186 bcopy(&l2pcb->dst, &pcb1->dst, sizeof(pcb1->dst));
1187 pcb1->channel = channel;
1189 /* Link new DLC to the session. We already hold s->session_mtx */
1190 LIST_INSERT_HEAD(&s->dlcs, pcb1, session_next);
1193 mtx_unlock(&pcb1->pcb_mtx);
1196 } /* ng_btsocket_rfcomm_connect_ind */
1199 * Process RFCOMM connect confirmation. Caller must hold s->session_mtx.
1203 ng_btsocket_rfcomm_connect_cfm(ng_btsocket_rfcomm_session_p s)
1205 ng_btsocket_rfcomm_pcb_p pcb = NULL, pcb_next = NULL;
1208 mtx_assert(&s->session_mtx, MA_OWNED);
1211 * Wake up all waiting sockets and send PN request for each of them.
1212 * Note that timeout already been set in ng_btsocket_rfcomm_connect()
1214 * Note: cannot use LIST_FOREACH because ng_btsocket_rfcomm_pcb_kill
1215 * will unlink DLC from the session
1218 for (pcb = LIST_FIRST(&s->dlcs); pcb != NULL; ) {
1219 mtx_lock(&pcb->pcb_mtx);
1220 pcb_next = LIST_NEXT(pcb, session_next);
1222 if (pcb->state == NG_BTSOCKET_RFCOMM_DLC_W4_CONNECT) {
1224 bcopy(&so2l2cap_pcb(s->l2so)->src, &pcb->src,
1227 error = ng_btsocket_rfcomm_send_pn(pcb);
1229 pcb->state = NG_BTSOCKET_RFCOMM_DLC_CONFIGURING;
1231 ng_btsocket_rfcomm_pcb_kill(pcb, error);
1234 mtx_unlock(&pcb->pcb_mtx);
1237 } /* ng_btsocket_rfcomm_connect_cfm */
1239 /*****************************************************************************
1240 *****************************************************************************
1242 *****************************************************************************
1243 *****************************************************************************/
1246 * Create new RFCOMM session. That function WILL NOT take ownership over l2so.
1247 * Caller MUST free l2so if function failed.
1251 ng_btsocket_rfcomm_session_create(ng_btsocket_rfcomm_session_p *sp,
1252 struct socket *l2so, bdaddr_p src, bdaddr_p dst,
1255 ng_btsocket_rfcomm_session_p s = NULL;
1256 struct sockaddr_l2cap l2sa;
1257 struct sockopt l2sopt;
1261 mtx_assert(&ng_btsocket_rfcomm_sessions_mtx, MA_OWNED);
1263 /* Allocate the RFCOMM session */
1264 s = malloc(sizeof(*s),
1265 M_NETGRAPH_BTSOCKET_RFCOMM, M_NOWAIT | M_ZERO);
1270 s->mtu = RFCOMM_DEFAULT_MTU;
1272 s->state = NG_BTSOCKET_RFCOMM_SESSION_CLOSED;
1273 NG_BT_MBUFQ_INIT(&s->outq, ifqmaxlen);
1276 * XXX Mark session mutex as DUPOK to prevent "duplicated lock of
1277 * the same type" message. When accepting new L2CAP connection
1278 * ng_btsocket_rfcomm_session_accept() holds both session mutexes
1279 * for "old" (accepting) session and "new" (created) session.
1282 mtx_init(&s->session_mtx, "btsocks_rfcomm_session_mtx", NULL,
1285 LIST_INIT(&s->dlcs);
1287 /* Prepare L2CAP socket */
1288 SOCKBUF_LOCK(&l2so->so_rcv);
1289 soupcall_set(l2so, SO_RCV, ng_btsocket_rfcomm_upcall, NULL);
1290 SOCKBUF_UNLOCK(&l2so->so_rcv);
1291 SOCKBUF_LOCK(&l2so->so_snd);
1292 soupcall_set(l2so, SO_SND, ng_btsocket_rfcomm_upcall, NULL);
1293 SOCKBUF_UNLOCK(&l2so->so_snd);
1294 l2so->so_state |= SS_NBIO;
1297 mtx_lock(&s->session_mtx);
1300 * "src" == NULL and "dst" == NULL means just create session.
1301 * caller must do the rest
1304 if (src == NULL && dst == NULL)
1308 * Set incoming MTU on L2CAP socket. It is RFCOMM session default MTU
1309 * plus 5 bytes: RFCOMM frame header, one extra byte for length and one
1310 * extra byte for credits.
1313 mtu = s->mtu + sizeof(struct rfcomm_frame_hdr) + 1 + 1;
1315 l2sopt.sopt_dir = SOPT_SET;
1316 l2sopt.sopt_level = SOL_L2CAP;
1317 l2sopt.sopt_name = SO_L2CAP_IMTU;
1318 l2sopt.sopt_val = (void *) &mtu;
1319 l2sopt.sopt_valsize = sizeof(mtu);
1320 l2sopt.sopt_td = NULL;
1322 error = sosetopt(s->l2so, &l2sopt);
1326 /* Bind socket to "src" address */
1327 l2sa.l2cap_len = sizeof(l2sa);
1328 l2sa.l2cap_family = AF_BLUETOOTH;
1329 l2sa.l2cap_psm = (dst == NULL)? htole16(NG_L2CAP_PSM_RFCOMM) : 0;
1330 bcopy(src, &l2sa.l2cap_bdaddr, sizeof(l2sa.l2cap_bdaddr));
1332 error = sobind(s->l2so, (struct sockaddr *) &l2sa, td);
1336 /* If "dst" is not NULL then initiate connect(), otherwise listen() */
1339 s->state = NG_BTSOCKET_RFCOMM_SESSION_LISTENING;
1341 error = solisten(s->l2so, 10, td);
1345 s->flags = NG_BTSOCKET_RFCOMM_SESSION_INITIATOR;
1346 s->state = NG_BTSOCKET_RFCOMM_SESSION_CONNECTING;
1348 l2sa.l2cap_len = sizeof(l2sa);
1349 l2sa.l2cap_family = AF_BLUETOOTH;
1350 l2sa.l2cap_psm = htole16(NG_L2CAP_PSM_RFCOMM);
1351 bcopy(dst, &l2sa.l2cap_bdaddr, sizeof(l2sa.l2cap_bdaddr));
1353 error = soconnect(s->l2so, (struct sockaddr *) &l2sa, td);
1359 LIST_INSERT_HEAD(&ng_btsocket_rfcomm_sessions, s, next);
1362 mtx_unlock(&s->session_mtx);
1367 mtx_unlock(&s->session_mtx);
1369 /* Return L2CAP socket back to its original state */
1370 SOCKBUF_LOCK(&l2so->so_rcv);
1371 soupcall_clear(s->l2so, SO_RCV);
1372 SOCKBUF_UNLOCK(&l2so->so_rcv);
1373 SOCKBUF_LOCK(&l2so->so_snd);
1374 soupcall_clear(s->l2so, SO_SND);
1375 SOCKBUF_UNLOCK(&l2so->so_snd);
1376 l2so->so_state &= ~SS_NBIO;
1378 mtx_destroy(&s->session_mtx);
1379 bzero(s, sizeof(*s));
1380 free(s, M_NETGRAPH_BTSOCKET_RFCOMM);
1383 } /* ng_btsocket_rfcomm_session_create */
1386 * Process accept() on RFCOMM session
1387 * XXX FIXME locking for "l2so"?
1391 ng_btsocket_rfcomm_session_accept(ng_btsocket_rfcomm_session_p s0)
1393 struct socket *l2so = NULL;
1394 struct sockaddr_l2cap *l2sa = NULL;
1395 ng_btsocket_l2cap_pcb_t *l2pcb = NULL;
1396 ng_btsocket_rfcomm_session_p s = NULL;
1399 mtx_assert(&ng_btsocket_rfcomm_sessions_mtx, MA_OWNED);
1400 mtx_assert(&s0->session_mtx, MA_OWNED);
1402 /* Check if there is a complete L2CAP connection in the queue */
1403 if ((error = s0->l2so->so_error) != 0) {
1404 NG_BTSOCKET_RFCOMM_ERR(
1405 "%s: Could not accept connection on L2CAP socket, error=%d\n", __func__, error);
1406 s0->l2so->so_error = 0;
1412 if (TAILQ_EMPTY(&s0->l2so->so_comp)) {
1414 if (s0->l2so->so_rcv.sb_state & SBS_CANTRCVMORE)
1415 return (ECONNABORTED);
1416 return (EWOULDBLOCK);
1419 /* Accept incoming L2CAP connection */
1420 l2so = TAILQ_FIRST(&s0->l2so->so_comp);
1422 panic("%s: l2so == NULL\n", __func__);
1424 TAILQ_REMOVE(&s0->l2so->so_comp, l2so, so_list);
1425 s0->l2so->so_qlen --;
1426 l2so->so_qstate &= ~SQ_COMP;
1427 l2so->so_head = NULL;
1430 l2so->so_state |= SS_NBIO;
1434 error = soaccept(l2so, (struct sockaddr **) &l2sa);
1436 NG_BTSOCKET_RFCOMM_ERR(
1437 "%s: soaccept() on L2CAP socket failed, error=%d\n", __func__, error);
1444 * Check if there is already active RFCOMM session between two devices.
1445 * If so then close L2CAP connection. We only support one RFCOMM session
1446 * between each pair of devices. Note that here we assume session in any
1447 * state. The session even could be in the middle of disconnecting.
1450 l2pcb = so2l2cap_pcb(l2so);
1451 s = ng_btsocket_rfcomm_session_by_addr(&l2pcb->src, &l2pcb->dst);
1453 /* Create a new RFCOMM session */
1454 error = ng_btsocket_rfcomm_session_create(&s, l2so, NULL, NULL,
1455 curthread /* XXX */);
1457 mtx_lock(&s->session_mtx);
1460 s->state = NG_BTSOCKET_RFCOMM_SESSION_CONNECTED;
1463 * Adjust MTU on incomming connection. Reserve 5 bytes:
1464 * RFCOMM frame header, one extra byte for length and
1465 * one extra byte for credits.
1468 s->mtu = min(l2pcb->imtu, l2pcb->omtu) -
1469 sizeof(struct rfcomm_frame_hdr) - 1 - 1;
1471 mtx_unlock(&s->session_mtx);
1473 NG_BTSOCKET_RFCOMM_ALERT(
1474 "%s: Failed to create new RFCOMM session, error=%d\n", __func__, error);
1479 NG_BTSOCKET_RFCOMM_WARN(
1480 "%s: Rejecting duplicating RFCOMM session between src=%x:%x:%x:%x:%x:%x and " \
1481 "dst=%x:%x:%x:%x:%x:%x, state=%d, flags=%#x\n", __func__,
1482 l2pcb->src.b[5], l2pcb->src.b[4], l2pcb->src.b[3],
1483 l2pcb->src.b[2], l2pcb->src.b[1], l2pcb->src.b[0],
1484 l2pcb->dst.b[5], l2pcb->dst.b[4], l2pcb->dst.b[3],
1485 l2pcb->dst.b[2], l2pcb->dst.b[1], l2pcb->dst.b[0],
1486 s->state, s->flags);
1493 } /* ng_btsocket_rfcomm_session_accept */
1496 * Process connect() on RFCOMM session
1497 * XXX FIXME locking for "l2so"?
1501 ng_btsocket_rfcomm_session_connect(ng_btsocket_rfcomm_session_p s)
1503 ng_btsocket_l2cap_pcb_p l2pcb = so2l2cap_pcb(s->l2so);
1506 mtx_assert(&s->session_mtx, MA_OWNED);
1508 /* First check if connection has failed */
1509 if ((error = s->l2so->so_error) != 0) {
1510 s->l2so->so_error = 0;
1512 NG_BTSOCKET_RFCOMM_ERR(
1513 "%s: Could not connect RFCOMM session, error=%d, state=%d, flags=%#x\n",
1514 __func__, error, s->state, s->flags);
1519 /* Is connection still in progress? */
1520 if (s->l2so->so_state & SS_ISCONNECTING)
1524 * If we got here then we are connected. Send SABM on DLCI 0 to
1525 * open multiplexor channel.
1529 s->state = NG_BTSOCKET_RFCOMM_SESSION_CONNECTED;
1532 * Adjust MTU on outgoing connection. Reserve 5 bytes: RFCOMM
1533 * frame header, one extra byte for length and one extra byte
1537 s->mtu = min(l2pcb->imtu, l2pcb->omtu) -
1538 sizeof(struct rfcomm_frame_hdr) - 1 - 1;
1540 error = ng_btsocket_rfcomm_send_command(s,RFCOMM_FRAME_SABM,0);
1542 error = ng_btsocket_rfcomm_task_wakeup();
1546 }/* ng_btsocket_rfcomm_session_connect */
1549 * Receive data on RFCOMM session
1550 * XXX FIXME locking for "l2so"?
1554 ng_btsocket_rfcomm_session_receive(ng_btsocket_rfcomm_session_p s)
1556 struct mbuf *m = NULL;
1558 int more, flags, error;
1560 mtx_assert(&s->session_mtx, MA_OWNED);
1562 /* Can we read from the L2CAP socket? */
1563 if (!soreadable(s->l2so))
1566 /* First check for error on L2CAP socket */
1567 if ((error = s->l2so->so_error) != 0) {
1568 s->l2so->so_error = 0;
1570 NG_BTSOCKET_RFCOMM_ERR(
1571 "%s: Could not receive data from L2CAP socket, error=%d, state=%d, flags=%#x\n",
1572 __func__, error, s->state, s->flags);
1578 * Read all packets from the L2CAP socket.
1579 * XXX FIXME/VERIFY is that correct? For now use m->m_nextpkt as
1580 * indication that there is more packets on the socket's buffer.
1581 * Also what should we use in uio.uio_resid?
1582 * May be s->mtu + sizeof(struct rfcomm_frame_hdr) + 1 + 1?
1585 for (more = 1; more; ) {
1586 /* Try to get next packet from socket */
1587 bzero(&uio, sizeof(uio));
1588 /* uio.uio_td = NULL; */
1589 uio.uio_resid = 1000000000;
1590 flags = MSG_DONTWAIT;
1593 error = soreceive(s->l2so, NULL, &uio, &m,
1594 (struct mbuf **) NULL, &flags);
1596 if (error == EWOULDBLOCK)
1597 return (0); /* XXX can happen? */
1599 NG_BTSOCKET_RFCOMM_ERR(
1600 "%s: Could not receive data from L2CAP socket, error=%d\n", __func__, error);
1605 more = (m->m_nextpkt != NULL);
1606 m->m_nextpkt = NULL;
1608 ng_btsocket_rfcomm_receive_frame(s, m);
1612 } /* ng_btsocket_rfcomm_session_receive */
1615 * Send data on RFCOMM session
1616 * XXX FIXME locking for "l2so"?
1620 ng_btsocket_rfcomm_session_send(ng_btsocket_rfcomm_session_p s)
1622 struct mbuf *m = NULL;
1625 mtx_assert(&s->session_mtx, MA_OWNED);
1627 /* Send as much as we can from the session queue */
1628 while (sowriteable(s->l2so)) {
1629 /* Check if socket still OK */
1630 if ((error = s->l2so->so_error) != 0) {
1631 s->l2so->so_error = 0;
1633 NG_BTSOCKET_RFCOMM_ERR(
1634 "%s: Detected error=%d on L2CAP socket, state=%d, flags=%#x\n",
1635 __func__, error, s->state, s->flags);
1640 NG_BT_MBUFQ_DEQUEUE(&s->outq, m);
1642 return (0); /* we are done */
1644 /* Call send function on the L2CAP socket */
1645 error = (*s->l2so->so_proto->pr_usrreqs->pru_send)(s->l2so,
1646 0, m, NULL, NULL, curthread /* XXX */);
1648 NG_BTSOCKET_RFCOMM_ERR(
1649 "%s: Could not send data to L2CAP socket, error=%d\n", __func__, error);
1656 } /* ng_btsocket_rfcomm_session_send */
1659 * Close and disconnect all DLCs for the given session. Caller must hold
1660 * s->sesson_mtx. Will wakeup session.
1664 ng_btsocket_rfcomm_session_clean(ng_btsocket_rfcomm_session_p s)
1666 ng_btsocket_rfcomm_pcb_p pcb = NULL, pcb_next = NULL;
1669 mtx_assert(&s->session_mtx, MA_OWNED);
1672 * Note: cannot use LIST_FOREACH because ng_btsocket_rfcomm_pcb_kill
1673 * will unlink DLC from the session
1676 for (pcb = LIST_FIRST(&s->dlcs); pcb != NULL; ) {
1677 mtx_lock(&pcb->pcb_mtx);
1678 pcb_next = LIST_NEXT(pcb, session_next);
1680 NG_BTSOCKET_RFCOMM_INFO(
1681 "%s: Disconnecting dlci=%d, state=%d, flags=%#x\n",
1682 __func__, pcb->dlci, pcb->state, pcb->flags);
1684 if (pcb->state == NG_BTSOCKET_RFCOMM_DLC_CONNECTED)
1687 error = ECONNREFUSED;
1689 ng_btsocket_rfcomm_pcb_kill(pcb, error);
1691 mtx_unlock(&pcb->pcb_mtx);
1694 } /* ng_btsocket_rfcomm_session_clean */
1697 * Process all DLCs on the session. Caller MUST hold s->session_mtx.
1701 ng_btsocket_rfcomm_session_process_pcb(ng_btsocket_rfcomm_session_p s)
1703 ng_btsocket_rfcomm_pcb_p pcb = NULL, pcb_next = NULL;
1706 mtx_assert(&s->session_mtx, MA_OWNED);
1709 * Note: cannot use LIST_FOREACH because ng_btsocket_rfcomm_pcb_kill
1710 * will unlink DLC from the session
1713 for (pcb = LIST_FIRST(&s->dlcs); pcb != NULL; ) {
1714 mtx_lock(&pcb->pcb_mtx);
1715 pcb_next = LIST_NEXT(pcb, session_next);
1717 switch (pcb->state) {
1720 * If DLC in W4_CONNECT state then we should check for both
1721 * timeout and detach.
1724 case NG_BTSOCKET_RFCOMM_DLC_W4_CONNECT:
1725 if (pcb->flags & NG_BTSOCKET_RFCOMM_DLC_DETACHED)
1726 ng_btsocket_rfcomm_pcb_kill(pcb, 0);
1727 else if (pcb->flags & NG_BTSOCKET_RFCOMM_DLC_TIMEDOUT)
1728 ng_btsocket_rfcomm_pcb_kill(pcb, ETIMEDOUT);
1732 * If DLC in CONFIGURING or CONNECTING state then we only
1733 * should check for timeout. If detach() was called then
1734 * DLC will be moved into DISCONNECTING state.
1737 case NG_BTSOCKET_RFCOMM_DLC_CONFIGURING:
1738 case NG_BTSOCKET_RFCOMM_DLC_CONNECTING:
1739 if (pcb->flags & NG_BTSOCKET_RFCOMM_DLC_TIMEDOUT)
1740 ng_btsocket_rfcomm_pcb_kill(pcb, ETIMEDOUT);
1744 * If DLC in CONNECTED state then we need to send data (if any)
1745 * from the socket's send queue. Note that we will send data
1746 * from either all sockets or none. This may overload session's
1747 * outgoing queue (but we do not check for that).
1749 * XXX FIXME need scheduler for RFCOMM sockets
1752 case NG_BTSOCKET_RFCOMM_DLC_CONNECTED:
1753 error = ng_btsocket_rfcomm_pcb_send(pcb, ALOT);
1755 ng_btsocket_rfcomm_pcb_kill(pcb, error);
1759 * If DLC in DISCONNECTING state then we must send DISC frame.
1760 * Note that if DLC has timeout set then we do not need to
1761 * resend DISC frame.
1763 * XXX FIXME need to drain all data from the socket's queue
1764 * if LINGER option was set
1767 case NG_BTSOCKET_RFCOMM_DLC_DISCONNECTING:
1768 if (!(pcb->flags & NG_BTSOCKET_RFCOMM_DLC_TIMO)) {
1769 error = ng_btsocket_rfcomm_send_command(
1770 pcb->session, RFCOMM_FRAME_DISC,
1773 ng_btsocket_rfcomm_timeout(pcb);
1775 ng_btsocket_rfcomm_pcb_kill(pcb, error);
1776 } else if (pcb->flags & NG_BTSOCKET_RFCOMM_DLC_TIMEDOUT)
1777 ng_btsocket_rfcomm_pcb_kill(pcb, ETIMEDOUT);
1780 /* case NG_BTSOCKET_RFCOMM_DLC_CLOSED: */
1782 panic("%s: Invalid DLC state=%d, flags=%#x\n",
1783 __func__, pcb->state, pcb->flags);
1787 mtx_unlock(&pcb->pcb_mtx);
1790 } /* ng_btsocket_rfcomm_session_process_pcb */
1793 * Find RFCOMM session between "src" and "dst".
1794 * Caller MUST hold ng_btsocket_rfcomm_sessions_mtx.
1797 static ng_btsocket_rfcomm_session_p
1798 ng_btsocket_rfcomm_session_by_addr(bdaddr_p src, bdaddr_p dst)
1800 ng_btsocket_rfcomm_session_p s = NULL;
1801 ng_btsocket_l2cap_pcb_p l2pcb = NULL;
1804 mtx_assert(&ng_btsocket_rfcomm_sessions_mtx, MA_OWNED);
1806 any_src = (bcmp(src, NG_HCI_BDADDR_ANY, sizeof(*src)) == 0);
1808 LIST_FOREACH(s, &ng_btsocket_rfcomm_sessions, next) {
1809 l2pcb = so2l2cap_pcb(s->l2so);
1811 if ((any_src || bcmp(&l2pcb->src, src, sizeof(*src)) == 0) &&
1812 bcmp(&l2pcb->dst, dst, sizeof(*dst)) == 0)
1817 } /* ng_btsocket_rfcomm_session_by_addr */
1819 /*****************************************************************************
1820 *****************************************************************************
1822 *****************************************************************************
1823 *****************************************************************************/
1826 * Process incoming RFCOMM frame. Caller must hold s->session_mtx.
1827 * XXX FIXME check frame length
1831 ng_btsocket_rfcomm_receive_frame(ng_btsocket_rfcomm_session_p s,
1834 struct rfcomm_frame_hdr *hdr = NULL;
1835 struct mbuf *m = NULL;
1837 u_int8_t dlci, type;
1840 mtx_assert(&s->session_mtx, MA_OWNED);
1842 /* Pullup as much as we can into first mbuf (for direct access) */
1843 length = min(m0->m_pkthdr.len, MHLEN);
1844 if (m0->m_len < length) {
1845 if ((m0 = m_pullup(m0, length)) == NULL) {
1846 NG_BTSOCKET_RFCOMM_ALERT(
1847 "%s: m_pullup(%d) failed\n", __func__, length);
1853 hdr = mtod(m0, struct rfcomm_frame_hdr *);
1854 dlci = RFCOMM_DLCI(hdr->address);
1855 type = RFCOMM_TYPE(hdr->control);
1857 /* Test EA bit in length. If not set then we have 2 bytes of length */
1858 if (!RFCOMM_EA(hdr->length)) {
1859 bcopy(&hdr->length, &length, sizeof(length));
1860 length = le16toh(length) >> 1;
1861 m_adj(m0, sizeof(*hdr) + 1);
1863 length = hdr->length >> 1;
1864 m_adj(m0, sizeof(*hdr));
1867 NG_BTSOCKET_RFCOMM_INFO(
1868 "%s: Got frame type=%#x, dlci=%d, length=%d, cr=%d, pf=%d, len=%d\n",
1869 __func__, type, dlci, length, RFCOMM_CR(hdr->address),
1870 RFCOMM_PF(hdr->control), m0->m_pkthdr.len);
1873 * Get FCS (the last byte in the frame)
1874 * XXX this will not work if mbuf chain ends with empty mbuf.
1875 * XXX let's hope it never happens :)
1878 for (m = m0; m->m_next != NULL; m = m->m_next)
1881 panic("%s: Empty mbuf at the end of the chain, len=%d\n",
1882 __func__, m->m_len);
1885 * Check FCS. We only need to calculate FCS on first 2 or 3 bytes
1886 * and already m_pullup'ed mbuf chain, so it should be safe.
1889 if (ng_btsocket_rfcomm_check_fcs((u_int8_t *) hdr, type, m->m_data[m->m_len - 1])) {
1890 NG_BTSOCKET_RFCOMM_ERR(
1891 "%s: Invalid RFCOMM packet. Bad checksum\n", __func__);
1897 m_adj(m0, -1); /* Trim FCS byte */
1900 * Process RFCOMM frame.
1902 * From TS 07.10 spec
1904 * "... In the case where a SABM or DISC command with the P bit set
1905 * to 0 is received then the received frame shall be discarded..."
1907 * "... If a unsolicited DM response is received then the frame shall
1908 * be processed irrespective of the P/F setting... "
1910 * "... The station may transmit response frames with the F bit set
1911 * to 0 at any opportunity on an asynchronous basis. However, in the
1912 * case where a UA response is received with the F bit set to 0 then
1913 * the received frame shall be discarded..."
1915 * From Bluetooth spec
1917 * "... When credit based flow control is being used, the meaning of
1918 * the P/F bit in the control field of the RFCOMM header is redefined
1919 * for UIH frames..."
1923 case RFCOMM_FRAME_SABM:
1924 if (RFCOMM_PF(hdr->control))
1925 error = ng_btsocket_rfcomm_receive_sabm(s, dlci);
1928 case RFCOMM_FRAME_DISC:
1929 if (RFCOMM_PF(hdr->control))
1930 error = ng_btsocket_rfcomm_receive_disc(s, dlci);
1933 case RFCOMM_FRAME_UA:
1934 if (RFCOMM_PF(hdr->control))
1935 error = ng_btsocket_rfcomm_receive_ua(s, dlci);
1938 case RFCOMM_FRAME_DM:
1939 error = ng_btsocket_rfcomm_receive_dm(s, dlci);
1942 case RFCOMM_FRAME_UIH:
1944 error = ng_btsocket_rfcomm_receive_mcc(s, m0);
1946 error = ng_btsocket_rfcomm_receive_uih(s, dlci,
1947 RFCOMM_PF(hdr->control), m0);
1953 NG_BTSOCKET_RFCOMM_ERR(
1954 "%s: Invalid RFCOMM packet. Unknown type=%#x\n", __func__, type);
1962 } /* ng_btsocket_rfcomm_receive_frame */
1965 * Process RFCOMM SABM frame
1969 ng_btsocket_rfcomm_receive_sabm(ng_btsocket_rfcomm_session_p s, int dlci)
1971 ng_btsocket_rfcomm_pcb_p pcb = NULL;
1974 mtx_assert(&s->session_mtx, MA_OWNED);
1976 NG_BTSOCKET_RFCOMM_INFO(
1977 "%s: Got SABM, session state=%d, flags=%#x, mtu=%d, dlci=%d\n",
1978 __func__, s->state, s->flags, s->mtu, dlci);
1980 /* DLCI == 0 means open multiplexor channel */
1983 case NG_BTSOCKET_RFCOMM_SESSION_CONNECTED:
1984 case NG_BTSOCKET_RFCOMM_SESSION_OPEN:
1985 error = ng_btsocket_rfcomm_send_command(s,
1986 RFCOMM_FRAME_UA, dlci);
1988 s->state = NG_BTSOCKET_RFCOMM_SESSION_OPEN;
1989 ng_btsocket_rfcomm_connect_cfm(s);
1991 s->state = NG_BTSOCKET_RFCOMM_SESSION_CLOSED;
1992 ng_btsocket_rfcomm_session_clean(s);
1997 NG_BTSOCKET_RFCOMM_WARN(
1998 "%s: Got SABM for session in invalid state state=%d, flags=%#x\n",
1999 __func__, s->state, s->flags);
2007 /* Make sure multiplexor channel is open */
2008 if (s->state != NG_BTSOCKET_RFCOMM_SESSION_OPEN) {
2009 NG_BTSOCKET_RFCOMM_ERR(
2010 "%s: Got SABM for dlci=%d with mulitplexor channel closed, state=%d, " \
2011 "flags=%#x\n", __func__, dlci, s->state, s->flags);
2017 * Check if we have this DLCI. This might happen when remote
2018 * peer uses PN command before actual open (SABM) happens.
2021 pcb = ng_btsocket_rfcomm_pcb_by_dlci(s, dlci);
2023 mtx_lock(&pcb->pcb_mtx);
2025 if (pcb->state != NG_BTSOCKET_RFCOMM_DLC_CONNECTING) {
2026 NG_BTSOCKET_RFCOMM_ERR(
2027 "%s: Got SABM for dlci=%d in invalid state=%d, flags=%#x\n",
2028 __func__, dlci, pcb->state, pcb->flags);
2029 mtx_unlock(&pcb->pcb_mtx);
2034 ng_btsocket_rfcomm_untimeout(pcb);
2036 error = ng_btsocket_rfcomm_send_command(s,RFCOMM_FRAME_UA,dlci);
2038 error = ng_btsocket_rfcomm_send_msc(pcb);
2041 pcb->state = NG_BTSOCKET_RFCOMM_DLC_CONNECTED;
2042 soisconnected(pcb->so);
2044 ng_btsocket_rfcomm_pcb_kill(pcb, error);
2046 mtx_unlock(&pcb->pcb_mtx);
2052 * We do not have requested DLCI, so it must be an incoming connection
2053 * with default parameters. Try to accept it.
2056 pcb = ng_btsocket_rfcomm_connect_ind(s, RFCOMM_SRVCHANNEL(dlci));
2058 mtx_lock(&pcb->pcb_mtx);
2062 error = ng_btsocket_rfcomm_send_command(s,RFCOMM_FRAME_UA,dlci);
2064 error = ng_btsocket_rfcomm_send_msc(pcb);
2067 pcb->state = NG_BTSOCKET_RFCOMM_DLC_CONNECTED;
2068 soisconnected(pcb->so);
2070 ng_btsocket_rfcomm_pcb_kill(pcb, error);
2072 mtx_unlock(&pcb->pcb_mtx);
2074 /* Nobody is listen()ing on the requested DLCI */
2075 error = ng_btsocket_rfcomm_send_command(s,RFCOMM_FRAME_DM,dlci);
2078 } /* ng_btsocket_rfcomm_receive_sabm */
2081 * Process RFCOMM DISC frame
2085 ng_btsocket_rfcomm_receive_disc(ng_btsocket_rfcomm_session_p s, int dlci)
2087 ng_btsocket_rfcomm_pcb_p pcb = NULL;
2090 mtx_assert(&s->session_mtx, MA_OWNED);
2092 NG_BTSOCKET_RFCOMM_INFO(
2093 "%s: Got DISC, session state=%d, flags=%#x, mtu=%d, dlci=%d\n",
2094 __func__, s->state, s->flags, s->mtu, dlci);
2096 /* DLCI == 0 means close multiplexor channel */
2098 /* XXX FIXME assume that remote side will close the socket */
2099 error = ng_btsocket_rfcomm_send_command(s, RFCOMM_FRAME_UA, 0);
2101 if (s->state == NG_BTSOCKET_RFCOMM_SESSION_DISCONNECTING)
2102 s->state = NG_BTSOCKET_RFCOMM_SESSION_CLOSED; /* XXX */
2104 s->state = NG_BTSOCKET_RFCOMM_SESSION_DISCONNECTING;
2106 s->state = NG_BTSOCKET_RFCOMM_SESSION_CLOSED; /* XXX */
2108 ng_btsocket_rfcomm_session_clean(s);
2110 pcb = ng_btsocket_rfcomm_pcb_by_dlci(s, dlci);
2114 mtx_lock(&pcb->pcb_mtx);
2116 NG_BTSOCKET_RFCOMM_INFO(
2117 "%s: Got DISC for dlci=%d, state=%d, flags=%#x\n",
2118 __func__, dlci, pcb->state, pcb->flags);
2120 error = ng_btsocket_rfcomm_send_command(s,
2121 RFCOMM_FRAME_UA, dlci);
2123 if (pcb->state == NG_BTSOCKET_RFCOMM_DLC_CONNECTED)
2128 ng_btsocket_rfcomm_pcb_kill(pcb, err);
2130 mtx_unlock(&pcb->pcb_mtx);
2132 NG_BTSOCKET_RFCOMM_WARN(
2133 "%s: Got DISC for non-existing dlci=%d\n", __func__, dlci);
2135 error = ng_btsocket_rfcomm_send_command(s,
2136 RFCOMM_FRAME_DM, dlci);
2141 } /* ng_btsocket_rfcomm_receive_disc */
2144 * Process RFCOMM UA frame
2148 ng_btsocket_rfcomm_receive_ua(ng_btsocket_rfcomm_session_p s, int dlci)
2150 ng_btsocket_rfcomm_pcb_p pcb = NULL;
2153 mtx_assert(&s->session_mtx, MA_OWNED);
2155 NG_BTSOCKET_RFCOMM_INFO(
2156 "%s: Got UA, session state=%d, flags=%#x, mtu=%d, dlci=%d\n",
2157 __func__, s->state, s->flags, s->mtu, dlci);
2159 /* dlci == 0 means multiplexor channel */
2162 case NG_BTSOCKET_RFCOMM_SESSION_CONNECTED:
2163 s->state = NG_BTSOCKET_RFCOMM_SESSION_OPEN;
2164 ng_btsocket_rfcomm_connect_cfm(s);
2167 case NG_BTSOCKET_RFCOMM_SESSION_DISCONNECTING:
2168 s->state = NG_BTSOCKET_RFCOMM_SESSION_CLOSED;
2169 ng_btsocket_rfcomm_session_clean(s);
2173 NG_BTSOCKET_RFCOMM_WARN(
2174 "%s: Got UA for session in invalid state=%d(%d), flags=%#x, mtu=%d\n",
2175 __func__, s->state, INITIATOR(s), s->flags,
2184 /* Check if we have this DLCI */
2185 pcb = ng_btsocket_rfcomm_pcb_by_dlci(s, dlci);
2187 mtx_lock(&pcb->pcb_mtx);
2189 NG_BTSOCKET_RFCOMM_INFO(
2190 "%s: Got UA for dlci=%d, state=%d, flags=%#x\n",
2191 __func__, dlci, pcb->state, pcb->flags);
2193 switch (pcb->state) {
2194 case NG_BTSOCKET_RFCOMM_DLC_CONNECTING:
2195 ng_btsocket_rfcomm_untimeout(pcb);
2197 error = ng_btsocket_rfcomm_send_msc(pcb);
2199 pcb->state = NG_BTSOCKET_RFCOMM_DLC_CONNECTED;
2200 soisconnected(pcb->so);
2204 case NG_BTSOCKET_RFCOMM_DLC_DISCONNECTING:
2205 ng_btsocket_rfcomm_pcb_kill(pcb, 0);
2209 NG_BTSOCKET_RFCOMM_WARN(
2210 "%s: Got UA for dlci=%d in invalid state=%d, flags=%#x\n",
2211 __func__, dlci, pcb->state, pcb->flags);
2216 mtx_unlock(&pcb->pcb_mtx);
2218 NG_BTSOCKET_RFCOMM_WARN(
2219 "%s: Got UA for non-existing dlci=%d\n", __func__, dlci);
2221 error = ng_btsocket_rfcomm_send_command(s,RFCOMM_FRAME_DM,dlci);
2225 } /* ng_btsocket_rfcomm_receive_ua */
2228 * Process RFCOMM DM frame
2232 ng_btsocket_rfcomm_receive_dm(ng_btsocket_rfcomm_session_p s, int dlci)
2234 ng_btsocket_rfcomm_pcb_p pcb = NULL;
2237 mtx_assert(&s->session_mtx, MA_OWNED);
2239 NG_BTSOCKET_RFCOMM_INFO(
2240 "%s: Got DM, session state=%d, flags=%#x, mtu=%d, dlci=%d\n",
2241 __func__, s->state, s->flags, s->mtu, dlci);
2243 /* DLCI == 0 means multiplexor channel */
2245 /* Disconnect all dlc's on the session */
2246 s->state = NG_BTSOCKET_RFCOMM_SESSION_CLOSED;
2247 ng_btsocket_rfcomm_session_clean(s);
2249 pcb = ng_btsocket_rfcomm_pcb_by_dlci(s, dlci);
2251 mtx_lock(&pcb->pcb_mtx);
2253 NG_BTSOCKET_RFCOMM_INFO(
2254 "%s: Got DM for dlci=%d, state=%d, flags=%#x\n",
2255 __func__, dlci, pcb->state, pcb->flags);
2257 if (pcb->state == NG_BTSOCKET_RFCOMM_DLC_CONNECTED)
2260 error = ECONNREFUSED;
2262 ng_btsocket_rfcomm_pcb_kill(pcb, error);
2264 mtx_unlock(&pcb->pcb_mtx);
2266 NG_BTSOCKET_RFCOMM_WARN(
2267 "%s: Got DM for non-existing dlci=%d\n", __func__, dlci);
2271 } /* ng_btsocket_rfcomm_receive_dm */
2274 * Process RFCOMM UIH frame (data)
2278 ng_btsocket_rfcomm_receive_uih(ng_btsocket_rfcomm_session_p s, int dlci,
2279 int pf, struct mbuf *m0)
2281 ng_btsocket_rfcomm_pcb_p pcb = NULL;
2284 mtx_assert(&s->session_mtx, MA_OWNED);
2286 NG_BTSOCKET_RFCOMM_INFO(
2287 "%s: Got UIH, session state=%d, flags=%#x, mtu=%d, dlci=%d, pf=%d, len=%d\n",
2288 __func__, s->state, s->flags, s->mtu, dlci, pf,
2291 /* XXX should we do it here? Check for session flow control */
2292 if (s->flags & NG_BTSOCKET_RFCOMM_SESSION_LFC) {
2293 NG_BTSOCKET_RFCOMM_WARN(
2294 "%s: Got UIH with session flow control asserted, state=%d, flags=%#x\n",
2295 __func__, s->state, s->flags);
2299 /* Check if we have this dlci */
2300 pcb = ng_btsocket_rfcomm_pcb_by_dlci(s, dlci);
2302 NG_BTSOCKET_RFCOMM_WARN(
2303 "%s: Got UIH for non-existing dlci=%d\n", __func__, dlci);
2304 error = ng_btsocket_rfcomm_send_command(s,RFCOMM_FRAME_DM,dlci);
2308 mtx_lock(&pcb->pcb_mtx);
2310 /* Check dlci state */
2311 if (pcb->state != NG_BTSOCKET_RFCOMM_DLC_CONNECTED) {
2312 NG_BTSOCKET_RFCOMM_WARN(
2313 "%s: Got UIH for dlci=%d in invalid state=%d, flags=%#x\n",
2314 __func__, dlci, pcb->state, pcb->flags);
2319 /* Check dlci flow control */
2320 if (((pcb->flags & NG_BTSOCKET_RFCOMM_DLC_CFC) && pcb->rx_cred <= 0) ||
2321 (pcb->lmodem & RFCOMM_MODEM_FC)) {
2322 NG_BTSOCKET_RFCOMM_ERR(
2323 "%s: Got UIH for dlci=%d with asserted flow control, state=%d, " \
2324 "flags=%#x, rx_cred=%d, lmodem=%#x\n",
2325 __func__, dlci, pcb->state, pcb->flags,
2326 pcb->rx_cred, pcb->lmodem);
2330 /* Did we get any credits? */
2331 if ((pcb->flags & NG_BTSOCKET_RFCOMM_DLC_CFC) && pf) {
2332 NG_BTSOCKET_RFCOMM_INFO(
2333 "%s: Got %d more credits for dlci=%d, state=%d, flags=%#x, " \
2334 "rx_cred=%d, tx_cred=%d\n",
2335 __func__, *mtod(m0, u_int8_t *), dlci, pcb->state,
2336 pcb->flags, pcb->rx_cred, pcb->tx_cred);
2338 pcb->tx_cred += *mtod(m0, u_int8_t *);
2341 /* Send more from the DLC. XXX check for errors? */
2342 ng_btsocket_rfcomm_pcb_send(pcb, ALOT);
2345 /* OK the of the rest of the mbuf is the data */
2346 if (m0->m_pkthdr.len > 0) {
2347 /* If we are using credit flow control decrease rx_cred here */
2348 if (pcb->flags & NG_BTSOCKET_RFCOMM_DLC_CFC) {
2349 /* Give remote peer more credits (if needed) */
2350 if (-- pcb->rx_cred <= RFCOMM_MAX_CREDITS / 2)
2351 ng_btsocket_rfcomm_send_credits(pcb);
2353 NG_BTSOCKET_RFCOMM_INFO(
2354 "%s: Remote side still has credits, dlci=%d, state=%d, flags=%#x, " \
2355 "rx_cred=%d, tx_cred=%d\n", __func__, dlci, pcb->state, pcb->flags,
2356 pcb->rx_cred, pcb->tx_cred);
2359 /* Check packet against mtu on dlci */
2360 if (m0->m_pkthdr.len > pcb->mtu) {
2361 NG_BTSOCKET_RFCOMM_ERR(
2362 "%s: Got oversized UIH for dlci=%d, state=%d, flags=%#x, mtu=%d, len=%d\n",
2363 __func__, dlci, pcb->state, pcb->flags,
2364 pcb->mtu, m0->m_pkthdr.len);
2367 } else if (m0->m_pkthdr.len > sbspace(&pcb->so->so_rcv)) {
2370 * This is really bad. Receive queue on socket does
2371 * not have enough space for the packet. We do not
2372 * have any other choice but drop the packet.
2375 NG_BTSOCKET_RFCOMM_ERR(
2376 "%s: Not enough space in socket receive queue. Dropping UIH for dlci=%d, " \
2377 "state=%d, flags=%#x, len=%d, space=%ld\n",
2378 __func__, dlci, pcb->state, pcb->flags,
2379 m0->m_pkthdr.len, sbspace(&pcb->so->so_rcv));
2383 /* Append packet to the socket receive queue */
2384 sbappend(&pcb->so->so_rcv, m0);
2391 mtx_unlock(&pcb->pcb_mtx);
2393 NG_FREE_M(m0); /* checks for != NULL */
2396 } /* ng_btsocket_rfcomm_receive_uih */
2399 * Process RFCOMM MCC command (Multiplexor)
2401 * From TS 07.10 spec
2403 * "5.4.3.1 Information Data
2405 * ...The frames (UIH) sent by the initiating station have the C/R bit set
2406 * to 1 and those sent by the responding station have the C/R bit set to 0..."
2408 * "5.4.6.2 Operating procedures
2410 * Messages always exist in pairs; a command message and a corresponding
2411 * response message. If the C/R bit is set to 1 the message is a command,
2412 * if it is set to 0 the message is a response...
2416 * NOTE: Notice that when UIH frames are used to convey information on DLCI 0
2417 * there are at least two different fields that contain a C/R bit, and the
2418 * bits are set of different form. The C/R bit in the Type field shall be set
2419 * as it is stated above, while the C/R bit in the Address field (see subclause
2420 * 5.2.1.2) shall be set as it is described in subclause 5.4.3.1."
2424 ng_btsocket_rfcomm_receive_mcc(ng_btsocket_rfcomm_session_p s, struct mbuf *m0)
2426 struct rfcomm_mcc_hdr *hdr = NULL;
2427 u_int8_t cr, type, length;
2429 mtx_assert(&s->session_mtx, MA_OWNED);
2432 * We can access data directly in the first mbuf, because we have
2433 * m_pullup()'ed mbuf chain in ng_btsocket_rfcomm_receive_frame().
2434 * All MCC commands should fit into single mbuf (except probably TEST).
2437 hdr = mtod(m0, struct rfcomm_mcc_hdr *);
2438 cr = RFCOMM_CR(hdr->type);
2439 type = RFCOMM_MCC_TYPE(hdr->type);
2440 length = RFCOMM_MCC_LENGTH(hdr->length);
2442 /* Check MCC frame length */
2443 if (sizeof(*hdr) + length != m0->m_pkthdr.len) {
2444 NG_BTSOCKET_RFCOMM_ERR(
2445 "%s: Invalid MCC frame length=%d, len=%d\n",
2446 __func__, length, m0->m_pkthdr.len);
2453 case RFCOMM_MCC_TEST:
2454 return (ng_btsocket_rfcomm_receive_test(s, m0));
2457 case RFCOMM_MCC_FCON:
2458 case RFCOMM_MCC_FCOFF:
2459 return (ng_btsocket_rfcomm_receive_fc(s, m0));
2462 case RFCOMM_MCC_MSC:
2463 return (ng_btsocket_rfcomm_receive_msc(s, m0));
2466 case RFCOMM_MCC_RPN:
2467 return (ng_btsocket_rfcomm_receive_rpn(s, m0));
2470 case RFCOMM_MCC_RLS:
2471 return (ng_btsocket_rfcomm_receive_rls(s, m0));
2475 return (ng_btsocket_rfcomm_receive_pn(s, m0));
2478 case RFCOMM_MCC_NSC:
2479 NG_BTSOCKET_RFCOMM_ERR(
2480 "%s: Got MCC NSC, type=%#x, cr=%d, length=%d, session state=%d, flags=%#x, " \
2481 "mtu=%d, len=%d\n", __func__, RFCOMM_MCC_TYPE(*((u_int8_t *)(hdr + 1))), cr,
2482 length, s->state, s->flags, s->mtu, m0->m_pkthdr.len);
2487 NG_BTSOCKET_RFCOMM_ERR(
2488 "%s: Got unknown MCC, type=%#x, cr=%d, length=%d, session state=%d, " \
2489 "flags=%#x, mtu=%d, len=%d\n",
2490 __func__, type, cr, length, s->state, s->flags,
2491 s->mtu, m0->m_pkthdr.len);
2493 /* Reuse mbuf to send NSC */
2494 hdr = mtod(m0, struct rfcomm_mcc_hdr *);
2495 m0->m_pkthdr.len = m0->m_len = sizeof(*hdr);
2497 /* Create MCC NSC header */
2498 hdr->type = RFCOMM_MKMCC_TYPE(0, RFCOMM_MCC_NSC);
2499 hdr->length = RFCOMM_MKLEN8(1);
2501 /* Put back MCC command type we did not like */
2502 m0->m_data[m0->m_len] = RFCOMM_MKMCC_TYPE(cr, type);
2503 m0->m_pkthdr.len ++;
2506 /* Send UIH frame */
2507 return (ng_btsocket_rfcomm_send_uih(s,
2508 RFCOMM_MKADDRESS(INITIATOR(s), 0), 0, 0, m0));
2513 } /* ng_btsocket_rfcomm_receive_mcc */
2516 * Receive RFCOMM TEST MCC command
2520 ng_btsocket_rfcomm_receive_test(ng_btsocket_rfcomm_session_p s, struct mbuf *m0)
2522 struct rfcomm_mcc_hdr *hdr = mtod(m0, struct rfcomm_mcc_hdr *);
2525 mtx_assert(&s->session_mtx, MA_OWNED);
2527 NG_BTSOCKET_RFCOMM_INFO(
2528 "%s: Got MCC TEST, cr=%d, length=%d, session state=%d, flags=%#x, mtu=%d, " \
2529 "len=%d\n", __func__, RFCOMM_CR(hdr->type), RFCOMM_MCC_LENGTH(hdr->length),
2530 s->state, s->flags, s->mtu, m0->m_pkthdr.len);
2532 if (RFCOMM_CR(hdr->type)) {
2533 hdr->type = RFCOMM_MKMCC_TYPE(0, RFCOMM_MCC_TEST);
2534 error = ng_btsocket_rfcomm_send_uih(s,
2535 RFCOMM_MKADDRESS(INITIATOR(s), 0), 0, 0, m0);
2537 NG_FREE_M(m0); /* XXX ignore response */
2540 } /* ng_btsocket_rfcomm_receive_test */
2543 * Receive RFCOMM FCON/FCOFF MCC command
2547 ng_btsocket_rfcomm_receive_fc(ng_btsocket_rfcomm_session_p s, struct mbuf *m0)
2549 struct rfcomm_mcc_hdr *hdr = mtod(m0, struct rfcomm_mcc_hdr *);
2550 u_int8_t type = RFCOMM_MCC_TYPE(hdr->type);
2553 mtx_assert(&s->session_mtx, MA_OWNED);
2556 * Turn ON/OFF aggregate flow on the entire session. When remote peer
2557 * asserted flow control no transmission shall occur except on dlci 0
2558 * (control channel).
2561 NG_BTSOCKET_RFCOMM_INFO(
2562 "%s: Got MCC FC%s, cr=%d, length=%d, session state=%d, flags=%#x, mtu=%d, " \
2563 "len=%d\n", __func__, (type == RFCOMM_MCC_FCON)? "ON" : "OFF",
2564 RFCOMM_CR(hdr->type), RFCOMM_MCC_LENGTH(hdr->length),
2565 s->state, s->flags, s->mtu, m0->m_pkthdr.len);
2567 if (RFCOMM_CR(hdr->type)) {
2568 if (type == RFCOMM_MCC_FCON)
2569 s->flags &= ~NG_BTSOCKET_RFCOMM_SESSION_RFC;
2571 s->flags |= NG_BTSOCKET_RFCOMM_SESSION_RFC;
2573 hdr->type = RFCOMM_MKMCC_TYPE(0, type);
2574 error = ng_btsocket_rfcomm_send_uih(s,
2575 RFCOMM_MKADDRESS(INITIATOR(s), 0), 0, 0, m0);
2577 NG_FREE_M(m0); /* XXX ignore response */
2580 } /* ng_btsocket_rfcomm_receive_fc */
2583 * Receive RFCOMM MSC MCC command
2587 ng_btsocket_rfcomm_receive_msc(ng_btsocket_rfcomm_session_p s, struct mbuf *m0)
2589 struct rfcomm_mcc_hdr *hdr = mtod(m0, struct rfcomm_mcc_hdr*);
2590 struct rfcomm_mcc_msc *msc = (struct rfcomm_mcc_msc *)(hdr+1);
2591 ng_btsocket_rfcomm_pcb_t *pcb = NULL;
2594 mtx_assert(&s->session_mtx, MA_OWNED);
2596 NG_BTSOCKET_RFCOMM_INFO(
2597 "%s: Got MCC MSC, dlci=%d, cr=%d, length=%d, session state=%d, flags=%#x, " \
2599 __func__, RFCOMM_DLCI(msc->address), RFCOMM_CR(hdr->type),
2600 RFCOMM_MCC_LENGTH(hdr->length), s->state, s->flags,
2601 s->mtu, m0->m_pkthdr.len);
2603 if (RFCOMM_CR(hdr->type)) {
2604 pcb = ng_btsocket_rfcomm_pcb_by_dlci(s, RFCOMM_DLCI(msc->address));
2606 NG_BTSOCKET_RFCOMM_WARN(
2607 "%s: Got MSC command for non-existing dlci=%d\n",
2608 __func__, RFCOMM_DLCI(msc->address));
2614 mtx_lock(&pcb->pcb_mtx);
2616 if (pcb->state != NG_BTSOCKET_RFCOMM_DLC_CONNECTING &&
2617 pcb->state != NG_BTSOCKET_RFCOMM_DLC_CONNECTED) {
2618 NG_BTSOCKET_RFCOMM_WARN(
2619 "%s: Got MSC on dlci=%d in invalid state=%d\n",
2620 __func__, RFCOMM_DLCI(msc->address),
2623 mtx_unlock(&pcb->pcb_mtx);
2629 pcb->rmodem = msc->modem; /* Update remote port signals */
2631 hdr->type = RFCOMM_MKMCC_TYPE(0, RFCOMM_MCC_MSC);
2632 error = ng_btsocket_rfcomm_send_uih(s,
2633 RFCOMM_MKADDRESS(INITIATOR(s), 0), 0, 0, m0);
2636 /* Send more data from DLC. XXX check for errors? */
2637 if (!(pcb->rmodem & RFCOMM_MODEM_FC) &&
2638 !(pcb->flags & NG_BTSOCKET_RFCOMM_DLC_CFC))
2639 ng_btsocket_rfcomm_pcb_send(pcb, ALOT);
2642 mtx_unlock(&pcb->pcb_mtx);
2644 NG_FREE_M(m0); /* XXX ignore response */
2647 } /* ng_btsocket_rfcomm_receive_msc */
2650 * Receive RFCOMM RPN MCC command
2651 * XXX FIXME do we need htole16/le16toh for RPN param_mask?
2655 ng_btsocket_rfcomm_receive_rpn(ng_btsocket_rfcomm_session_p s, struct mbuf *m0)
2657 struct rfcomm_mcc_hdr *hdr = mtod(m0, struct rfcomm_mcc_hdr *);
2658 struct rfcomm_mcc_rpn *rpn = (struct rfcomm_mcc_rpn *)(hdr + 1);
2660 u_int16_t param_mask;
2661 u_int8_t bit_rate, data_bits, stop_bits, parity,
2662 flow_control, xon_char, xoff_char;
2664 mtx_assert(&s->session_mtx, MA_OWNED);
2666 NG_BTSOCKET_RFCOMM_INFO(
2667 "%s: Got MCC RPN, dlci=%d, cr=%d, length=%d, session state=%d, flags=%#x, " \
2669 __func__, RFCOMM_DLCI(rpn->dlci), RFCOMM_CR(hdr->type),
2670 RFCOMM_MCC_LENGTH(hdr->length), s->state, s->flags,
2671 s->mtu, m0->m_pkthdr.len);
2673 if (RFCOMM_CR(hdr->type)) {
2674 param_mask = RFCOMM_RPN_PM_ALL;
2676 if (RFCOMM_MCC_LENGTH(hdr->length) == 1) {
2677 /* Request - return default setting */
2678 bit_rate = RFCOMM_RPN_BR_115200;
2679 data_bits = RFCOMM_RPN_DATA_8;
2680 stop_bits = RFCOMM_RPN_STOP_1;
2681 parity = RFCOMM_RPN_PARITY_NONE;
2682 flow_control = RFCOMM_RPN_FLOW_NONE;
2683 xon_char = RFCOMM_RPN_XON_CHAR;
2684 xoff_char = RFCOMM_RPN_XOFF_CHAR;
2687 * Ignore/accept bit_rate, 8 bits, 1 stop bit, no
2688 * parity, no flow control lines, default XON/XOFF
2692 bit_rate = rpn->bit_rate;
2693 rpn->param_mask = le16toh(rpn->param_mask); /* XXX */
2695 data_bits = RFCOMM_RPN_DATA_BITS(rpn->line_settings);
2696 if (rpn->param_mask & RFCOMM_RPN_PM_DATA &&
2697 data_bits != RFCOMM_RPN_DATA_8) {
2698 data_bits = RFCOMM_RPN_DATA_8;
2699 param_mask ^= RFCOMM_RPN_PM_DATA;
2702 stop_bits = RFCOMM_RPN_STOP_BITS(rpn->line_settings);
2703 if (rpn->param_mask & RFCOMM_RPN_PM_STOP &&
2704 stop_bits != RFCOMM_RPN_STOP_1) {
2705 stop_bits = RFCOMM_RPN_STOP_1;
2706 param_mask ^= RFCOMM_RPN_PM_STOP;
2709 parity = RFCOMM_RPN_PARITY(rpn->line_settings);
2710 if (rpn->param_mask & RFCOMM_RPN_PM_PARITY &&
2711 parity != RFCOMM_RPN_PARITY_NONE) {
2712 parity = RFCOMM_RPN_PARITY_NONE;
2713 param_mask ^= RFCOMM_RPN_PM_PARITY;
2716 flow_control = rpn->flow_control;
2717 if (rpn->param_mask & RFCOMM_RPN_PM_FLOW &&
2718 flow_control != RFCOMM_RPN_FLOW_NONE) {
2719 flow_control = RFCOMM_RPN_FLOW_NONE;
2720 param_mask ^= RFCOMM_RPN_PM_FLOW;
2723 xon_char = rpn->xon_char;
2724 if (rpn->param_mask & RFCOMM_RPN_PM_XON &&
2725 xon_char != RFCOMM_RPN_XON_CHAR) {
2726 xon_char = RFCOMM_RPN_XON_CHAR;
2727 param_mask ^= RFCOMM_RPN_PM_XON;
2730 xoff_char = rpn->xoff_char;
2731 if (rpn->param_mask & RFCOMM_RPN_PM_XOFF &&
2732 xoff_char != RFCOMM_RPN_XOFF_CHAR) {
2733 xoff_char = RFCOMM_RPN_XOFF_CHAR;
2734 param_mask ^= RFCOMM_RPN_PM_XOFF;
2738 rpn->bit_rate = bit_rate;
2739 rpn->line_settings = RFCOMM_MKRPN_LINE_SETTINGS(data_bits,
2741 rpn->flow_control = flow_control;
2742 rpn->xon_char = xon_char;
2743 rpn->xoff_char = xoff_char;
2744 rpn->param_mask = htole16(param_mask); /* XXX */
2746 m0->m_pkthdr.len = m0->m_len = sizeof(*hdr) + sizeof(*rpn);
2748 hdr->type = RFCOMM_MKMCC_TYPE(0, RFCOMM_MCC_RPN);
2749 error = ng_btsocket_rfcomm_send_uih(s,
2750 RFCOMM_MKADDRESS(INITIATOR(s), 0), 0, 0, m0);
2752 NG_FREE_M(m0); /* XXX ignore response */
2755 } /* ng_btsocket_rfcomm_receive_rpn */
2758 * Receive RFCOMM RLS MCC command
2762 ng_btsocket_rfcomm_receive_rls(ng_btsocket_rfcomm_session_p s, struct mbuf *m0)
2764 struct rfcomm_mcc_hdr *hdr = mtod(m0, struct rfcomm_mcc_hdr *);
2765 struct rfcomm_mcc_rls *rls = (struct rfcomm_mcc_rls *)(hdr + 1);
2768 mtx_assert(&s->session_mtx, MA_OWNED);
2771 * XXX FIXME Do we have to do anything else here? Remote peer tries to
2772 * tell us something about DLCI. Just report what we have received and
2773 * return back received values as required by TS 07.10 spec.
2776 NG_BTSOCKET_RFCOMM_INFO(
2777 "%s: Got MCC RLS, dlci=%d, status=%#x, cr=%d, length=%d, session state=%d, " \
2778 "flags=%#x, mtu=%d, len=%d\n",
2779 __func__, RFCOMM_DLCI(rls->address), rls->status,
2780 RFCOMM_CR(hdr->type), RFCOMM_MCC_LENGTH(hdr->length),
2781 s->state, s->flags, s->mtu, m0->m_pkthdr.len);
2783 if (RFCOMM_CR(hdr->type)) {
2784 if (rls->status & 0x1)
2785 NG_BTSOCKET_RFCOMM_ERR(
2786 "%s: Got RLS dlci=%d, error=%#x\n", __func__, RFCOMM_DLCI(rls->address),
2789 hdr->type = RFCOMM_MKMCC_TYPE(0, RFCOMM_MCC_RLS);
2790 error = ng_btsocket_rfcomm_send_uih(s,
2791 RFCOMM_MKADDRESS(INITIATOR(s), 0), 0, 0, m0);
2793 NG_FREE_M(m0); /* XXX ignore responses */
2796 } /* ng_btsocket_rfcomm_receive_rls */
2799 * Receive RFCOMM PN MCC command
2803 ng_btsocket_rfcomm_receive_pn(ng_btsocket_rfcomm_session_p s, struct mbuf *m0)
2805 struct rfcomm_mcc_hdr *hdr = mtod(m0, struct rfcomm_mcc_hdr*);
2806 struct rfcomm_mcc_pn *pn = (struct rfcomm_mcc_pn *)(hdr+1);
2807 ng_btsocket_rfcomm_pcb_t *pcb = NULL;
2810 mtx_assert(&s->session_mtx, MA_OWNED);
2812 NG_BTSOCKET_RFCOMM_INFO(
2813 "%s: Got MCC PN, dlci=%d, cr=%d, length=%d, flow_control=%#x, priority=%d, " \
2814 "ack_timer=%d, mtu=%d, max_retrans=%d, credits=%d, session state=%d, " \
2815 "flags=%#x, session mtu=%d, len=%d\n",
2816 __func__, pn->dlci, RFCOMM_CR(hdr->type),
2817 RFCOMM_MCC_LENGTH(hdr->length), pn->flow_control, pn->priority,
2818 pn->ack_timer, le16toh(pn->mtu), pn->max_retrans, pn->credits,
2819 s->state, s->flags, s->mtu, m0->m_pkthdr.len);
2821 if (pn->dlci == 0) {
2822 NG_BTSOCKET_RFCOMM_ERR("%s: Zero dlci in MCC PN\n", __func__);
2828 /* Check if we have this dlci */
2829 pcb = ng_btsocket_rfcomm_pcb_by_dlci(s, pn->dlci);
2831 mtx_lock(&pcb->pcb_mtx);
2833 if (RFCOMM_CR(hdr->type)) {
2835 ng_btsocket_rfcomm_set_pn(pcb, 1, pn->flow_control,
2836 pn->credits, pn->mtu);
2838 if (pcb->flags & NG_BTSOCKET_RFCOMM_DLC_CFC) {
2839 pn->flow_control = 0xe0;
2840 pn->credits = RFCOMM_DEFAULT_CREDITS;
2842 pn->flow_control = 0;
2846 hdr->type = RFCOMM_MKMCC_TYPE(0, RFCOMM_MCC_PN);
2847 error = ng_btsocket_rfcomm_send_uih(s,
2848 RFCOMM_MKADDRESS(INITIATOR(s), 0),
2851 /* PN Response - proceed with SABM. Timeout still set */
2852 if (pcb->state == NG_BTSOCKET_RFCOMM_DLC_CONFIGURING) {
2853 ng_btsocket_rfcomm_set_pn(pcb, 0,
2854 pn->flow_control, pn->credits, pn->mtu);
2856 pcb->state = NG_BTSOCKET_RFCOMM_DLC_CONNECTING;
2857 error = ng_btsocket_rfcomm_send_command(s,
2858 RFCOMM_FRAME_SABM, pn->dlci);
2860 NG_BTSOCKET_RFCOMM_WARN(
2861 "%s: Got PN response for dlci=%d in invalid state=%d\n",
2862 __func__, pn->dlci, pcb->state);
2867 mtx_unlock(&pcb->pcb_mtx);
2868 } else if (RFCOMM_CR(hdr->type)) {
2869 /* PN request to non-existing dlci - incomming connection */
2870 pcb = ng_btsocket_rfcomm_connect_ind(s,
2871 RFCOMM_SRVCHANNEL(pn->dlci));
2873 mtx_lock(&pcb->pcb_mtx);
2875 pcb->dlci = pn->dlci;
2877 ng_btsocket_rfcomm_set_pn(pcb, 1, pn->flow_control,
2878 pn->credits, pn->mtu);
2880 if (pcb->flags & NG_BTSOCKET_RFCOMM_DLC_CFC) {
2881 pn->flow_control = 0xe0;
2882 pn->credits = RFCOMM_DEFAULT_CREDITS;
2884 pn->flow_control = 0;
2888 hdr->type = RFCOMM_MKMCC_TYPE(0, RFCOMM_MCC_PN);
2889 error = ng_btsocket_rfcomm_send_uih(s,
2890 RFCOMM_MKADDRESS(INITIATOR(s), 0),
2894 ng_btsocket_rfcomm_timeout(pcb);
2895 pcb->state = NG_BTSOCKET_RFCOMM_DLC_CONNECTING;
2896 soisconnecting(pcb->so);
2898 ng_btsocket_rfcomm_pcb_kill(pcb, error);
2900 mtx_unlock(&pcb->pcb_mtx);
2902 /* Nobody is listen()ing on this channel */
2903 error = ng_btsocket_rfcomm_send_command(s,
2904 RFCOMM_FRAME_DM, pn->dlci);
2908 NG_FREE_M(m0); /* XXX ignore response to non-existing dlci */
2911 } /* ng_btsocket_rfcomm_receive_pn */
2914 * Set PN parameters for dlci. Caller must hold pcb->pcb_mtx.
2916 * From Bluetooth spec.
2918 * "... The CL1 - CL4 field is completely redefined. (In TS07.10 this defines
2919 * the convergence layer to use, which is not applicable to RFCOMM. In RFCOMM,
2920 * in Bluetooth versions up to 1.0B, this field was forced to 0).
2922 * In the PN request sent prior to a DLC establishment, this field must contain
2923 * the value 15 (0xF), indicating support of credit based flow control in the
2924 * sender. See Table 5.3 below. If the PN response contains any other value
2925 * than 14 (0xE) in this field, it is inferred that the peer RFCOMM entity is
2926 * not supporting the credit based flow control feature. (This is only possible
2927 * if the peer RFCOMM implementation is only conforming to Bluetooth version
2928 * 1.0B.) If a PN request is sent on an already open DLC, then this field must
2929 * contain the value zero; it is not possible to set initial credits more
2930 * than once per DLC activation. A responding implementation must set this
2931 * field in the PN response to 14 (0xE), if (and only if) the value in the PN
2932 * request was 15..."
2936 ng_btsocket_rfcomm_set_pn(ng_btsocket_rfcomm_pcb_p pcb, u_int8_t cr,
2937 u_int8_t flow_control, u_int8_t credits, u_int16_t mtu)
2939 mtx_assert(&pcb->pcb_mtx, MA_OWNED);
2941 pcb->mtu = le16toh(mtu);
2944 if (flow_control == 0xf0) {
2945 pcb->flags |= NG_BTSOCKET_RFCOMM_DLC_CFC;
2946 pcb->tx_cred = credits;
2948 pcb->flags &= ~NG_BTSOCKET_RFCOMM_DLC_CFC;
2952 if (flow_control == 0xe0) {
2953 pcb->flags |= NG_BTSOCKET_RFCOMM_DLC_CFC;
2954 pcb->tx_cred = credits;
2956 pcb->flags &= ~NG_BTSOCKET_RFCOMM_DLC_CFC;
2961 NG_BTSOCKET_RFCOMM_INFO(
2962 "%s: cr=%d, dlci=%d, state=%d, flags=%#x, mtu=%d, rx_cred=%d, tx_cred=%d\n",
2963 __func__, cr, pcb->dlci, pcb->state, pcb->flags, pcb->mtu,
2964 pcb->rx_cred, pcb->tx_cred);
2965 } /* ng_btsocket_rfcomm_set_pn */
2968 * Send RFCOMM SABM/DISC/UA/DM frames. Caller must hold s->session_mtx
2972 ng_btsocket_rfcomm_send_command(ng_btsocket_rfcomm_session_p s,
2973 u_int8_t type, u_int8_t dlci)
2975 struct rfcomm_cmd_hdr *hdr = NULL;
2976 struct mbuf *m = NULL;
2979 mtx_assert(&s->session_mtx, MA_OWNED);
2981 NG_BTSOCKET_RFCOMM_INFO(
2982 "%s: Sending command type %#x, session state=%d, flags=%#x, mtu=%d, dlci=%d\n",
2983 __func__, type, s->state, s->flags, s->mtu, dlci);
2986 case RFCOMM_FRAME_SABM:
2987 case RFCOMM_FRAME_DISC:
2991 case RFCOMM_FRAME_UA:
2992 case RFCOMM_FRAME_DM:
2997 panic("%s: Invalid frame type=%#x\n", __func__, type);
3002 MGETHDR(m, M_DONTWAIT, MT_DATA);
3006 m->m_pkthdr.len = m->m_len = sizeof(*hdr);
3008 hdr = mtod(m, struct rfcomm_cmd_hdr *);
3009 hdr->address = RFCOMM_MKADDRESS(cr, dlci);
3010 hdr->control = RFCOMM_MKCONTROL(type, 1);
3011 hdr->length = RFCOMM_MKLEN8(0);
3012 hdr->fcs = ng_btsocket_rfcomm_fcs3((u_int8_t *) hdr);
3014 NG_BT_MBUFQ_ENQUEUE(&s->outq, m);
3017 } /* ng_btsocket_rfcomm_send_command */
3020 * Send RFCOMM UIH frame. Caller must hold s->session_mtx
3024 ng_btsocket_rfcomm_send_uih(ng_btsocket_rfcomm_session_p s, u_int8_t address,
3025 u_int8_t pf, u_int8_t credits, struct mbuf *data)
3027 struct rfcomm_frame_hdr *hdr = NULL;
3028 struct mbuf *m = NULL, *mcrc = NULL;
3031 mtx_assert(&s->session_mtx, MA_OWNED);
3033 MGETHDR(m, M_DONTWAIT, MT_DATA);
3038 m->m_pkthdr.len = m->m_len = sizeof(*hdr);
3040 MGET(mcrc, M_DONTWAIT, MT_DATA);
3047 /* Fill UIH frame header */
3048 hdr = mtod(m, struct rfcomm_frame_hdr *);
3049 hdr->address = address;
3050 hdr->control = RFCOMM_MKCONTROL(RFCOMM_FRAME_UIH, pf);
3053 mcrc->m_data[0] = ng_btsocket_rfcomm_fcs2((u_int8_t *) hdr);
3055 /* Put length back */
3056 length = (data != NULL)? data->m_pkthdr.len : 0;
3058 u_int16_t l = htole16(RFCOMM_MKLEN16(length));
3060 bcopy(&l, &hdr->length, sizeof(l));
3064 hdr->length = RFCOMM_MKLEN8(length);
3067 m->m_data[m->m_len] = credits;
3075 m->m_pkthdr.len += length;
3082 NG_BTSOCKET_RFCOMM_INFO(
3083 "%s: Sending UIH state=%d, flags=%#x, address=%d, length=%d, pf=%d, " \
3084 "credits=%d, len=%d\n",
3085 __func__, s->state, s->flags, address, length, pf, credits,
3088 NG_BT_MBUFQ_ENQUEUE(&s->outq, m);
3091 } /* ng_btsocket_rfcomm_send_uih */
3094 * Send MSC request. Caller must hold pcb->pcb_mtx and pcb->session->session_mtx
3098 ng_btsocket_rfcomm_send_msc(ng_btsocket_rfcomm_pcb_p pcb)
3100 struct mbuf *m = NULL;
3101 struct rfcomm_mcc_hdr *hdr = NULL;
3102 struct rfcomm_mcc_msc *msc = NULL;
3104 mtx_assert(&pcb->session->session_mtx, MA_OWNED);
3105 mtx_assert(&pcb->pcb_mtx, MA_OWNED);
3107 MGETHDR(m, M_DONTWAIT, MT_DATA);
3111 m->m_pkthdr.len = m->m_len = sizeof(*hdr) + sizeof(*msc);
3113 hdr = mtod(m, struct rfcomm_mcc_hdr *);
3114 msc = (struct rfcomm_mcc_msc *)(hdr + 1);
3116 hdr->type = RFCOMM_MKMCC_TYPE(1, RFCOMM_MCC_MSC);
3117 hdr->length = RFCOMM_MKLEN8(sizeof(*msc));
3119 msc->address = RFCOMM_MKADDRESS(1, pcb->dlci);
3120 msc->modem = pcb->lmodem;
3122 NG_BTSOCKET_RFCOMM_INFO(
3123 "%s: Sending MSC dlci=%d, state=%d, flags=%#x, address=%d, modem=%#x\n",
3124 __func__, pcb->dlci, pcb->state, pcb->flags, msc->address,
3127 return (ng_btsocket_rfcomm_send_uih(pcb->session,
3128 RFCOMM_MKADDRESS(INITIATOR(pcb->session), 0), 0, 0, m));
3129 } /* ng_btsocket_rfcomm_send_msc */
3132 * Send PN request. Caller must hold pcb->pcb_mtx and pcb->session->session_mtx
3136 ng_btsocket_rfcomm_send_pn(ng_btsocket_rfcomm_pcb_p pcb)
3138 struct mbuf *m = NULL;
3139 struct rfcomm_mcc_hdr *hdr = NULL;
3140 struct rfcomm_mcc_pn *pn = NULL;
3142 mtx_assert(&pcb->session->session_mtx, MA_OWNED);
3143 mtx_assert(&pcb->pcb_mtx, MA_OWNED);
3145 MGETHDR(m, M_DONTWAIT, MT_DATA);
3149 m->m_pkthdr.len = m->m_len = sizeof(*hdr) + sizeof(*pn);
3151 hdr = mtod(m, struct rfcomm_mcc_hdr *);
3152 pn = (struct rfcomm_mcc_pn *)(hdr + 1);
3154 hdr->type = RFCOMM_MKMCC_TYPE(1, RFCOMM_MCC_PN);
3155 hdr->length = RFCOMM_MKLEN8(sizeof(*pn));
3157 pn->dlci = pcb->dlci;
3160 * Set default DLCI priority as described in GSM 07.10
3161 * (ETSI TS 101 369) clause 5.6 page 42
3164 pn->priority = (pcb->dlci < 56)? (((pcb->dlci >> 3) << 3) + 7) : 61;
3166 pn->mtu = htole16(pcb->mtu);
3167 pn->max_retrans = 0;
3169 if (pcb->flags & NG_BTSOCKET_RFCOMM_DLC_CFC) {
3170 pn->flow_control = 0xf0;
3171 pn->credits = pcb->rx_cred;
3173 pn->flow_control = 0;
3177 NG_BTSOCKET_RFCOMM_INFO(
3178 "%s: Sending PN dlci=%d, state=%d, flags=%#x, mtu=%d, flow_control=%#x, " \
3179 "credits=%d\n", __func__, pcb->dlci, pcb->state, pcb->flags, pcb->mtu,
3180 pn->flow_control, pn->credits);
3182 return (ng_btsocket_rfcomm_send_uih(pcb->session,
3183 RFCOMM_MKADDRESS(INITIATOR(pcb->session), 0), 0, 0, m));
3184 } /* ng_btsocket_rfcomm_send_pn */
3187 * Calculate and send credits based on available space in receive buffer
3191 ng_btsocket_rfcomm_send_credits(ng_btsocket_rfcomm_pcb_p pcb)
3196 mtx_assert(&pcb->pcb_mtx, MA_OWNED);
3197 mtx_assert(&pcb->session->session_mtx, MA_OWNED);
3199 NG_BTSOCKET_RFCOMM_INFO(
3200 "%s: Sending more credits, dlci=%d, state=%d, flags=%#x, mtu=%d, " \
3201 "space=%ld, tx_cred=%d, rx_cred=%d\n",
3202 __func__, pcb->dlci, pcb->state, pcb->flags, pcb->mtu,
3203 sbspace(&pcb->so->so_rcv), pcb->tx_cred, pcb->rx_cred);
3205 credits = sbspace(&pcb->so->so_rcv) / pcb->mtu;
3207 if (pcb->rx_cred + credits > RFCOMM_MAX_CREDITS)
3208 credits = RFCOMM_MAX_CREDITS - pcb->rx_cred;
3210 error = ng_btsocket_rfcomm_send_uih(
3212 RFCOMM_MKADDRESS(INITIATOR(pcb->session),
3213 pcb->dlci), 1, credits, NULL);
3215 pcb->rx_cred += credits;
3217 NG_BTSOCKET_RFCOMM_INFO(
3218 "%s: Gave remote side %d more credits, dlci=%d, state=%d, flags=%#x, " \
3219 "rx_cred=%d, tx_cred=%d\n", __func__, credits, pcb->dlci, pcb->state,
3220 pcb->flags, pcb->rx_cred, pcb->tx_cred);
3222 NG_BTSOCKET_RFCOMM_ERR(
3223 "%s: Could not send credits, error=%d, dlci=%d, state=%d, flags=%#x, " \
3224 "mtu=%d, space=%ld, tx_cred=%d, rx_cred=%d\n",
3225 __func__, error, pcb->dlci, pcb->state,
3226 pcb->flags, pcb->mtu, sbspace(&pcb->so->so_rcv),
3227 pcb->tx_cred, pcb->rx_cred);
3231 } /* ng_btsocket_rfcomm_send_credits */
3233 /*****************************************************************************
3234 *****************************************************************************
3236 *****************************************************************************
3237 *****************************************************************************/
3240 * Send data from socket send buffer
3241 * Caller must hold pcb->pcb_mtx and pcb->session->session_mtx
3245 ng_btsocket_rfcomm_pcb_send(ng_btsocket_rfcomm_pcb_p pcb, int limit)
3247 struct mbuf *m = NULL;
3248 int sent, length, error;
3250 mtx_assert(&pcb->session->session_mtx, MA_OWNED);
3251 mtx_assert(&pcb->pcb_mtx, MA_OWNED);
3253 if (pcb->flags & NG_BTSOCKET_RFCOMM_DLC_CFC)
3254 limit = min(limit, pcb->tx_cred);
3255 else if (!(pcb->rmodem & RFCOMM_MODEM_FC))
3256 limit = min(limit, RFCOMM_MAX_CREDITS); /* XXX ??? */
3261 NG_BTSOCKET_RFCOMM_INFO(
3262 "%s: Could not send - remote flow control asserted, dlci=%d, flags=%#x, " \
3263 "rmodem=%#x, tx_cred=%d\n",
3264 __func__, pcb->dlci, pcb->flags, pcb->rmodem,
3270 for (error = 0, sent = 0; sent < limit; sent ++) {
3271 length = min(pcb->mtu, pcb->so->so_snd.sb_cc);
3275 /* Get the chunk from the socket's send buffer */
3276 m = ng_btsocket_rfcomm_prepare_packet(&pcb->so->so_snd, length);
3282 sbdrop(&pcb->so->so_snd, length);
3284 error = ng_btsocket_rfcomm_send_uih(pcb->session,
3285 RFCOMM_MKADDRESS(INITIATOR(pcb->session),
3286 pcb->dlci), 0, 0, m);
3291 if (pcb->flags & NG_BTSOCKET_RFCOMM_DLC_CFC)
3292 pcb->tx_cred -= sent;
3294 if (error == 0 && sent > 0) {
3295 pcb->flags &= ~NG_BTSOCKET_RFCOMM_DLC_SENDING;
3300 } /* ng_btsocket_rfcomm_pcb_send */
3303 * Unlink and disconnect DLC. If ng_btsocket_rfcomm_pcb_kill() returns
3304 * non zero value than socket has no reference and has to be detached.
3305 * Caller must hold pcb->pcb_mtx and pcb->session->session_mtx
3309 ng_btsocket_rfcomm_pcb_kill(ng_btsocket_rfcomm_pcb_p pcb, int error)
3311 ng_btsocket_rfcomm_session_p s = pcb->session;
3313 NG_BTSOCKET_RFCOMM_INFO(
3314 "%s: Killing DLC, so=%p, dlci=%d, state=%d, flags=%#x, error=%d\n",
3315 __func__, pcb->so, pcb->dlci, pcb->state, pcb->flags, error);
3317 if (pcb->session == NULL)
3318 panic("%s: DLC without session, pcb=%p, state=%d, flags=%#x\n",
3319 __func__, pcb, pcb->state, pcb->flags);
3321 mtx_assert(&pcb->session->session_mtx, MA_OWNED);
3322 mtx_assert(&pcb->pcb_mtx, MA_OWNED);
3324 if (pcb->flags & NG_BTSOCKET_RFCOMM_DLC_TIMO)
3325 ng_btsocket_rfcomm_untimeout(pcb);
3327 /* Detach DLC from the session. Does not matter which state DLC in */
3328 LIST_REMOVE(pcb, session_next);
3329 pcb->session = NULL;
3331 /* Change DLC state and wakeup all sleepers */
3332 pcb->state = NG_BTSOCKET_RFCOMM_DLC_CLOSED;
3333 pcb->so->so_error = error;
3334 soisdisconnected(pcb->so);
3335 wakeup(&pcb->state);
3337 /* Check if we have any DLCs left on the session */
3338 if (LIST_EMPTY(&s->dlcs) && INITIATOR(s)) {
3339 NG_BTSOCKET_RFCOMM_INFO(
3340 "%s: Disconnecting session, state=%d, flags=%#x, mtu=%d\n",
3341 __func__, s->state, s->flags, s->mtu);
3344 case NG_BTSOCKET_RFCOMM_SESSION_CLOSED:
3345 case NG_BTSOCKET_RFCOMM_SESSION_DISCONNECTING:
3347 * Do not have to do anything here. We can get here
3348 * when L2CAP connection was terminated or we have
3349 * received DISC on multiplexor channel
3353 case NG_BTSOCKET_RFCOMM_SESSION_OPEN:
3354 /* Send DISC on multiplexor channel */
3355 error = ng_btsocket_rfcomm_send_command(s,
3356 RFCOMM_FRAME_DISC, 0);
3358 s->state = NG_BTSOCKET_RFCOMM_SESSION_DISCONNECTING;
3363 case NG_BTSOCKET_RFCOMM_SESSION_CONNECTING:
3364 case NG_BTSOCKET_RFCOMM_SESSION_CONNECTED:
3365 s->state = NG_BTSOCKET_RFCOMM_SESSION_CLOSED;
3368 /* case NG_BTSOCKET_RFCOMM_SESSION_LISTENING: */
3370 panic("%s: Invalid session state=%d, flags=%#x\n",
3371 __func__, s->state, s->flags);
3375 ng_btsocket_rfcomm_task_wakeup();
3377 } /* ng_btsocket_rfcomm_pcb_kill */
3380 * Look for given dlci for given RFCOMM session. Caller must hold s->session_mtx
3383 static ng_btsocket_rfcomm_pcb_p
3384 ng_btsocket_rfcomm_pcb_by_dlci(ng_btsocket_rfcomm_session_p s, int dlci)
3386 ng_btsocket_rfcomm_pcb_p pcb = NULL;
3388 mtx_assert(&s->session_mtx, MA_OWNED);
3390 LIST_FOREACH(pcb, &s->dlcs, session_next)
3391 if (pcb->dlci == dlci)
3395 } /* ng_btsocket_rfcomm_pcb_by_dlci */
3398 * Look for socket that listens on given src address and given channel
3401 static ng_btsocket_rfcomm_pcb_p
3402 ng_btsocket_rfcomm_pcb_listener(bdaddr_p src, int channel)
3404 ng_btsocket_rfcomm_pcb_p pcb = NULL, pcb1 = NULL;
3406 mtx_lock(&ng_btsocket_rfcomm_sockets_mtx);
3408 LIST_FOREACH(pcb, &ng_btsocket_rfcomm_sockets, next) {
3409 if (pcb->channel != channel ||
3410 !(pcb->so->so_options & SO_ACCEPTCONN))
3413 if (bcmp(&pcb->src, src, sizeof(*src)) == 0)
3416 if (bcmp(&pcb->src, NG_HCI_BDADDR_ANY, sizeof(bdaddr_t)) == 0)
3420 mtx_unlock(&ng_btsocket_rfcomm_sockets_mtx);
3422 return ((pcb != NULL)? pcb : pcb1);
3423 } /* ng_btsocket_rfcomm_pcb_listener */
3425 /*****************************************************************************
3426 *****************************************************************************
3428 *****************************************************************************
3429 *****************************************************************************/
3432 * Set timeout. Caller MUST hold pcb_mtx
3436 ng_btsocket_rfcomm_timeout(ng_btsocket_rfcomm_pcb_p pcb)
3438 mtx_assert(&pcb->pcb_mtx, MA_OWNED);
3440 if (!(pcb->flags & NG_BTSOCKET_RFCOMM_DLC_TIMO)) {
3441 pcb->flags |= NG_BTSOCKET_RFCOMM_DLC_TIMO;
3442 pcb->flags &= ~NG_BTSOCKET_RFCOMM_DLC_TIMEDOUT;
3443 pcb->timo = timeout(ng_btsocket_rfcomm_process_timeout, pcb,
3444 ng_btsocket_rfcomm_timo * hz);
3446 panic("%s: Duplicated socket timeout?!\n", __func__);
3447 } /* ng_btsocket_rfcomm_timeout */
3450 * Unset pcb timeout. Caller MUST hold pcb_mtx
3454 ng_btsocket_rfcomm_untimeout(ng_btsocket_rfcomm_pcb_p pcb)
3456 mtx_assert(&pcb->pcb_mtx, MA_OWNED);
3458 if (pcb->flags & NG_BTSOCKET_RFCOMM_DLC_TIMO) {
3459 untimeout(ng_btsocket_rfcomm_process_timeout, pcb, pcb->timo);
3460 pcb->flags &= ~NG_BTSOCKET_RFCOMM_DLC_TIMO;
3461 pcb->flags &= ~NG_BTSOCKET_RFCOMM_DLC_TIMEDOUT;
3463 panic("%s: No socket timeout?!\n", __func__);
3464 } /* ng_btsocket_rfcomm_timeout */
3467 * Process pcb timeout
3471 ng_btsocket_rfcomm_process_timeout(void *xpcb)
3473 ng_btsocket_rfcomm_pcb_p pcb = (ng_btsocket_rfcomm_pcb_p) xpcb;
3475 mtx_lock(&pcb->pcb_mtx);
3477 NG_BTSOCKET_RFCOMM_INFO(
3478 "%s: Timeout, so=%p, dlci=%d, state=%d, flags=%#x\n",
3479 __func__, pcb->so, pcb->dlci, pcb->state, pcb->flags);
3481 pcb->flags &= ~NG_BTSOCKET_RFCOMM_DLC_TIMO;
3482 pcb->flags |= NG_BTSOCKET_RFCOMM_DLC_TIMEDOUT;
3484 switch (pcb->state) {
3485 case NG_BTSOCKET_RFCOMM_DLC_CONFIGURING:
3486 case NG_BTSOCKET_RFCOMM_DLC_CONNECTING:
3487 pcb->state = NG_BTSOCKET_RFCOMM_DLC_DISCONNECTING;
3490 case NG_BTSOCKET_RFCOMM_DLC_W4_CONNECT:
3491 case NG_BTSOCKET_RFCOMM_DLC_DISCONNECTING:
3496 "%s: DLC timeout in invalid state, dlci=%d, state=%d, flags=%#x\n",
3497 __func__, pcb->dlci, pcb->state, pcb->flags);
3501 ng_btsocket_rfcomm_task_wakeup();
3503 mtx_unlock(&pcb->pcb_mtx);
3504 } /* ng_btsocket_rfcomm_process_timeout */
3507 * Get up to length bytes from the socket buffer
3510 static struct mbuf *
3511 ng_btsocket_rfcomm_prepare_packet(struct sockbuf *sb, int length)
3513 struct mbuf *top = NULL, *m = NULL, *n = NULL, *nextpkt = NULL;
3514 int mlen, noff, len;
3516 MGETHDR(top, M_DONTWAIT, MT_DATA);
3520 top->m_pkthdr.len = length;
3526 nextpkt = n->m_nextpkt;
3529 while (length > 0 && n != NULL) {
3530 len = min(mlen - m->m_len, n->m_len - noff);
3534 bcopy(mtod(n, caddr_t)+noff, mtod(m, caddr_t)+m->m_len, len);
3539 if (length > 0 && m->m_len == mlen) {
3540 MGET(m->m_next, M_DONTWAIT, MT_DATA);
3541 if (m->m_next == NULL) {
3551 if (noff == n->m_len) {
3558 nextpkt = (n != NULL)? n->m_nextpkt : NULL;
3563 panic("%s: length=%d\n", __func__, length);
3564 if (length > 0 && n == NULL)
3565 panic("%s: bogus length=%d, n=%p\n", __func__, length, n);
3568 } /* ng_btsocket_rfcomm_prepare_packet */