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>
58 #include <netgraph/ng_message.h>
59 #include <netgraph/netgraph.h>
60 #include <netgraph/bluetooth/include/ng_bluetooth.h>
61 #include <netgraph/bluetooth/include/ng_hci.h>
62 #include <netgraph/bluetooth/include/ng_l2cap.h>
63 #include <netgraph/bluetooth/include/ng_btsocket.h>
64 #include <netgraph/bluetooth/include/ng_btsocket_l2cap.h>
65 #include <netgraph/bluetooth/include/ng_btsocket_rfcomm.h>
68 #ifdef NG_SEPARATE_MALLOC
69 static MALLOC_DEFINE(M_NETGRAPH_BTSOCKET_RFCOMM, "netgraph_btsocks_rfcomm",
70 "Netgraph Bluetooth RFCOMM sockets");
72 #define M_NETGRAPH_BTSOCKET_RFCOMM M_NETGRAPH
73 #endif /* NG_SEPARATE_MALLOC */
76 #define NG_BTSOCKET_RFCOMM_INFO \
77 if (ng_btsocket_rfcomm_debug_level >= NG_BTSOCKET_INFO_LEVEL && \
78 ppsratecheck(&ng_btsocket_rfcomm_lasttime, &ng_btsocket_rfcomm_curpps, 1)) \
81 #define NG_BTSOCKET_RFCOMM_WARN \
82 if (ng_btsocket_rfcomm_debug_level >= NG_BTSOCKET_WARN_LEVEL && \
83 ppsratecheck(&ng_btsocket_rfcomm_lasttime, &ng_btsocket_rfcomm_curpps, 1)) \
86 #define NG_BTSOCKET_RFCOMM_ERR \
87 if (ng_btsocket_rfcomm_debug_level >= NG_BTSOCKET_ERR_LEVEL && \
88 ppsratecheck(&ng_btsocket_rfcomm_lasttime, &ng_btsocket_rfcomm_curpps, 1)) \
91 #define NG_BTSOCKET_RFCOMM_ALERT \
92 if (ng_btsocket_rfcomm_debug_level >= NG_BTSOCKET_ALERT_LEVEL && \
93 ppsratecheck(&ng_btsocket_rfcomm_lasttime, &ng_btsocket_rfcomm_curpps, 1)) \
98 /* Local prototypes */
99 static int ng_btsocket_rfcomm_upcall
100 (struct socket *so, void *arg, int waitflag);
101 static void ng_btsocket_rfcomm_sessions_task
102 (void *ctx, int pending);
103 static void ng_btsocket_rfcomm_session_task
104 (ng_btsocket_rfcomm_session_p s);
105 #define ng_btsocket_rfcomm_task_wakeup() \
106 taskqueue_enqueue(taskqueue_swi_giant, &ng_btsocket_rfcomm_task)
108 static ng_btsocket_rfcomm_pcb_p ng_btsocket_rfcomm_connect_ind
109 (ng_btsocket_rfcomm_session_p s, int channel);
110 static void ng_btsocket_rfcomm_connect_cfm
111 (ng_btsocket_rfcomm_session_p s);
113 static int ng_btsocket_rfcomm_session_create
114 (ng_btsocket_rfcomm_session_p *sp, struct socket *l2so,
115 bdaddr_p src, bdaddr_p dst, struct thread *td);
116 static int ng_btsocket_rfcomm_session_accept
117 (ng_btsocket_rfcomm_session_p s0);
118 static int ng_btsocket_rfcomm_session_connect
119 (ng_btsocket_rfcomm_session_p s);
120 static int ng_btsocket_rfcomm_session_receive
121 (ng_btsocket_rfcomm_session_p s);
122 static int ng_btsocket_rfcomm_session_send
123 (ng_btsocket_rfcomm_session_p s);
124 static void ng_btsocket_rfcomm_session_clean
125 (ng_btsocket_rfcomm_session_p s);
126 static void ng_btsocket_rfcomm_session_process_pcb
127 (ng_btsocket_rfcomm_session_p s);
128 static ng_btsocket_rfcomm_session_p ng_btsocket_rfcomm_session_by_addr
129 (bdaddr_p src, bdaddr_p dst);
131 static int ng_btsocket_rfcomm_receive_frame
132 (ng_btsocket_rfcomm_session_p s, struct mbuf *m0);
133 static int ng_btsocket_rfcomm_receive_sabm
134 (ng_btsocket_rfcomm_session_p s, int dlci);
135 static int ng_btsocket_rfcomm_receive_disc
136 (ng_btsocket_rfcomm_session_p s, int dlci);
137 static int ng_btsocket_rfcomm_receive_ua
138 (ng_btsocket_rfcomm_session_p s, int dlci);
139 static int ng_btsocket_rfcomm_receive_dm
140 (ng_btsocket_rfcomm_session_p s, int dlci);
141 static int ng_btsocket_rfcomm_receive_uih
142 (ng_btsocket_rfcomm_session_p s, int dlci, int pf, struct mbuf *m0);
143 static int ng_btsocket_rfcomm_receive_mcc
144 (ng_btsocket_rfcomm_session_p s, struct mbuf *m0);
145 static int ng_btsocket_rfcomm_receive_test
146 (ng_btsocket_rfcomm_session_p s, struct mbuf *m0);
147 static int ng_btsocket_rfcomm_receive_fc
148 (ng_btsocket_rfcomm_session_p s, struct mbuf *m0);
149 static int ng_btsocket_rfcomm_receive_msc
150 (ng_btsocket_rfcomm_session_p s, struct mbuf *m0);
151 static int ng_btsocket_rfcomm_receive_rpn
152 (ng_btsocket_rfcomm_session_p s, struct mbuf *m0);
153 static int ng_btsocket_rfcomm_receive_rls
154 (ng_btsocket_rfcomm_session_p s, struct mbuf *m0);
155 static int ng_btsocket_rfcomm_receive_pn
156 (ng_btsocket_rfcomm_session_p s, struct mbuf *m0);
157 static void ng_btsocket_rfcomm_set_pn
158 (ng_btsocket_rfcomm_pcb_p pcb, u_int8_t cr, u_int8_t flow_control,
159 u_int8_t credits, u_int16_t mtu);
161 static int ng_btsocket_rfcomm_send_command
162 (ng_btsocket_rfcomm_session_p s, u_int8_t type, u_int8_t dlci);
163 static int ng_btsocket_rfcomm_send_uih
164 (ng_btsocket_rfcomm_session_p s, u_int8_t address, u_int8_t pf,
165 u_int8_t credits, struct mbuf *data);
166 static int ng_btsocket_rfcomm_send_msc
167 (ng_btsocket_rfcomm_pcb_p pcb);
168 static int ng_btsocket_rfcomm_send_pn
169 (ng_btsocket_rfcomm_pcb_p pcb);
170 static int ng_btsocket_rfcomm_send_credits
171 (ng_btsocket_rfcomm_pcb_p pcb);
173 static int ng_btsocket_rfcomm_pcb_send
174 (ng_btsocket_rfcomm_pcb_p pcb, int limit);
175 static void ng_btsocket_rfcomm_pcb_kill
176 (ng_btsocket_rfcomm_pcb_p pcb, int error);
177 static ng_btsocket_rfcomm_pcb_p ng_btsocket_rfcomm_pcb_by_dlci
178 (ng_btsocket_rfcomm_session_p s, int dlci);
179 static ng_btsocket_rfcomm_pcb_p ng_btsocket_rfcomm_pcb_listener
180 (bdaddr_p src, int channel);
182 static void ng_btsocket_rfcomm_timeout
183 (ng_btsocket_rfcomm_pcb_p pcb);
184 static void ng_btsocket_rfcomm_untimeout
185 (ng_btsocket_rfcomm_pcb_p pcb);
186 static void ng_btsocket_rfcomm_process_timeout
189 static struct mbuf * ng_btsocket_rfcomm_prepare_packet
190 (struct sockbuf *sb, int length);
193 extern int ifqmaxlen;
194 static u_int32_t ng_btsocket_rfcomm_debug_level;
195 static u_int32_t ng_btsocket_rfcomm_timo;
196 struct task ng_btsocket_rfcomm_task;
197 static LIST_HEAD(, ng_btsocket_rfcomm_session) ng_btsocket_rfcomm_sessions;
198 static struct mtx ng_btsocket_rfcomm_sessions_mtx;
199 static LIST_HEAD(, ng_btsocket_rfcomm_pcb) ng_btsocket_rfcomm_sockets;
200 static struct mtx ng_btsocket_rfcomm_sockets_mtx;
201 static struct timeval ng_btsocket_rfcomm_lasttime;
202 static int ng_btsocket_rfcomm_curpps;
205 SYSCTL_DECL(_net_bluetooth_rfcomm_sockets);
206 static SYSCTL_NODE(_net_bluetooth_rfcomm_sockets, OID_AUTO, stream, CTLFLAG_RW,
207 0, "Bluetooth STREAM RFCOMM sockets family");
208 SYSCTL_UINT(_net_bluetooth_rfcomm_sockets_stream, OID_AUTO, debug_level,
210 &ng_btsocket_rfcomm_debug_level, NG_BTSOCKET_INFO_LEVEL,
211 "Bluetooth STREAM RFCOMM sockets debug level");
212 SYSCTL_UINT(_net_bluetooth_rfcomm_sockets_stream, OID_AUTO, timeout,
214 &ng_btsocket_rfcomm_timo, 60,
215 "Bluetooth STREAM RFCOMM sockets timeout");
217 /*****************************************************************************
218 *****************************************************************************
220 *****************************************************************************
221 *****************************************************************************/
223 static u_int8_t ng_btsocket_rfcomm_crc_table[256] = {
224 0x00, 0x91, 0xe3, 0x72, 0x07, 0x96, 0xe4, 0x75,
225 0x0e, 0x9f, 0xed, 0x7c, 0x09, 0x98, 0xea, 0x7b,
226 0x1c, 0x8d, 0xff, 0x6e, 0x1b, 0x8a, 0xf8, 0x69,
227 0x12, 0x83, 0xf1, 0x60, 0x15, 0x84, 0xf6, 0x67,
229 0x38, 0xa9, 0xdb, 0x4a, 0x3f, 0xae, 0xdc, 0x4d,
230 0x36, 0xa7, 0xd5, 0x44, 0x31, 0xa0, 0xd2, 0x43,
231 0x24, 0xb5, 0xc7, 0x56, 0x23, 0xb2, 0xc0, 0x51,
232 0x2a, 0xbb, 0xc9, 0x58, 0x2d, 0xbc, 0xce, 0x5f,
234 0x70, 0xe1, 0x93, 0x02, 0x77, 0xe6, 0x94, 0x05,
235 0x7e, 0xef, 0x9d, 0x0c, 0x79, 0xe8, 0x9a, 0x0b,
236 0x6c, 0xfd, 0x8f, 0x1e, 0x6b, 0xfa, 0x88, 0x19,
237 0x62, 0xf3, 0x81, 0x10, 0x65, 0xf4, 0x86, 0x17,
239 0x48, 0xd9, 0xab, 0x3a, 0x4f, 0xde, 0xac, 0x3d,
240 0x46, 0xd7, 0xa5, 0x34, 0x41, 0xd0, 0xa2, 0x33,
241 0x54, 0xc5, 0xb7, 0x26, 0x53, 0xc2, 0xb0, 0x21,
242 0x5a, 0xcb, 0xb9, 0x28, 0x5d, 0xcc, 0xbe, 0x2f,
244 0xe0, 0x71, 0x03, 0x92, 0xe7, 0x76, 0x04, 0x95,
245 0xee, 0x7f, 0x0d, 0x9c, 0xe9, 0x78, 0x0a, 0x9b,
246 0xfc, 0x6d, 0x1f, 0x8e, 0xfb, 0x6a, 0x18, 0x89,
247 0xf2, 0x63, 0x11, 0x80, 0xf5, 0x64, 0x16, 0x87,
249 0xd8, 0x49, 0x3b, 0xaa, 0xdf, 0x4e, 0x3c, 0xad,
250 0xd6, 0x47, 0x35, 0xa4, 0xd1, 0x40, 0x32, 0xa3,
251 0xc4, 0x55, 0x27, 0xb6, 0xc3, 0x52, 0x20, 0xb1,
252 0xca, 0x5b, 0x29, 0xb8, 0xcd, 0x5c, 0x2e, 0xbf,
254 0x90, 0x01, 0x73, 0xe2, 0x97, 0x06, 0x74, 0xe5,
255 0x9e, 0x0f, 0x7d, 0xec, 0x99, 0x08, 0x7a, 0xeb,
256 0x8c, 0x1d, 0x6f, 0xfe, 0x8b, 0x1a, 0x68, 0xf9,
257 0x82, 0x13, 0x61, 0xf0, 0x85, 0x14, 0x66, 0xf7,
259 0xa8, 0x39, 0x4b, 0xda, 0xaf, 0x3e, 0x4c, 0xdd,
260 0xa6, 0x37, 0x45, 0xd4, 0xa1, 0x30, 0x42, 0xd3,
261 0xb4, 0x25, 0x57, 0xc6, 0xb3, 0x22, 0x50, 0xc1,
262 0xba, 0x2b, 0x59, 0xc8, 0xbd, 0x2c, 0x5e, 0xcf
267 ng_btsocket_rfcomm_crc(u_int8_t *data, int length)
272 crc = ng_btsocket_rfcomm_crc_table[crc ^ *data++];
275 } /* ng_btsocket_rfcomm_crc */
279 ng_btsocket_rfcomm_fcs2(u_int8_t *data)
281 return (0xff - ng_btsocket_rfcomm_crc(data, 2));
282 } /* ng_btsocket_rfcomm_fcs2 */
286 ng_btsocket_rfcomm_fcs3(u_int8_t *data)
288 return (0xff - ng_btsocket_rfcomm_crc(data, 3));
289 } /* ng_btsocket_rfcomm_fcs3 */
294 * From Bluetooth spec
296 * "... In 07.10, the frame check sequence (FCS) is calculated on different
297 * sets of fields for different frame types. These are the fields that the
298 * FCS are calculated on:
300 * For SABM, DISC, UA, DM frames: on Address, Control and length field.
301 * For UIH frames: on Address and Control field.
303 * (This is stated here for clarification, and to set the standard for RFCOMM;
304 * the fields included in FCS calculation have actually changed in version
305 * 7.0.0 of TS 07.10, but RFCOMM will not change the FCS calculation scheme
306 * from the one above.) ..."
310 ng_btsocket_rfcomm_check_fcs(u_int8_t *data, int type, u_int8_t fcs)
312 if (type != RFCOMM_FRAME_UIH)
313 return (ng_btsocket_rfcomm_fcs3(data) != fcs);
315 return (ng_btsocket_rfcomm_fcs2(data) != fcs);
316 } /* ng_btsocket_rfcomm_check_fcs */
318 /*****************************************************************************
319 *****************************************************************************
321 *****************************************************************************
322 *****************************************************************************/
325 * Initialize everything
329 ng_btsocket_rfcomm_init(void)
332 /* Skip initialization of globals for non-default instances. */
333 if (!IS_DEFAULT_VNET(curvnet))
336 ng_btsocket_rfcomm_debug_level = NG_BTSOCKET_WARN_LEVEL;
337 ng_btsocket_rfcomm_timo = 60;
340 TASK_INIT(&ng_btsocket_rfcomm_task, 0,
341 ng_btsocket_rfcomm_sessions_task, NULL);
343 /* RFCOMM sessions list */
344 LIST_INIT(&ng_btsocket_rfcomm_sessions);
345 mtx_init(&ng_btsocket_rfcomm_sessions_mtx,
346 "btsocks_rfcomm_sessions_mtx", NULL, MTX_DEF);
348 /* RFCOMM sockets list */
349 LIST_INIT(&ng_btsocket_rfcomm_sockets);
350 mtx_init(&ng_btsocket_rfcomm_sockets_mtx,
351 "btsocks_rfcomm_sockets_mtx", NULL, MTX_DEF);
352 } /* ng_btsocket_rfcomm_init */
355 * Abort connection on socket
359 ng_btsocket_rfcomm_abort(struct socket *so)
362 so->so_error = ECONNABORTED;
363 (void)ng_btsocket_rfcomm_disconnect(so);
364 } /* ng_btsocket_rfcomm_abort */
367 ng_btsocket_rfcomm_close(struct socket *so)
370 (void)ng_btsocket_rfcomm_disconnect(so);
371 } /* ng_btsocket_rfcomm_close */
374 * Accept connection on socket. Nothing to do here, socket must be connected
375 * and ready, so just return peer address and be done with it.
379 ng_btsocket_rfcomm_accept(struct socket *so, struct sockaddr **nam)
381 return (ng_btsocket_rfcomm_peeraddr(so, nam));
382 } /* ng_btsocket_rfcomm_accept */
385 * Create and attach new socket
389 ng_btsocket_rfcomm_attach(struct socket *so, int proto, struct thread *td)
391 ng_btsocket_rfcomm_pcb_p pcb = so2rfcomm_pcb(so);
394 /* Check socket and protocol */
395 if (so->so_type != SOCK_STREAM)
396 return (ESOCKTNOSUPPORT);
398 #if 0 /* XXX sonewconn() calls "pru_attach" with proto == 0 */
400 if (proto != BLUETOOTH_PROTO_RFCOMM)
401 return (EPROTONOSUPPORT);
407 /* Reserve send and receive space if it is not reserved yet */
408 if ((so->so_snd.sb_hiwat == 0) || (so->so_rcv.sb_hiwat == 0)) {
409 error = soreserve(so, NG_BTSOCKET_RFCOMM_SENDSPACE,
410 NG_BTSOCKET_RFCOMM_RECVSPACE);
415 /* Allocate the PCB */
416 pcb = malloc(sizeof(*pcb),
417 M_NETGRAPH_BTSOCKET_RFCOMM, M_NOWAIT | M_ZERO);
421 /* Link the PCB and the socket */
422 so->so_pcb = (caddr_t) pcb;
426 pcb->state = NG_BTSOCKET_RFCOMM_DLC_CLOSED;
427 pcb->flags = NG_BTSOCKET_RFCOMM_DLC_CFC;
430 pcb->rmodem = (RFCOMM_MODEM_RTC | RFCOMM_MODEM_RTR | RFCOMM_MODEM_DV);
432 pcb->mtu = RFCOMM_DEFAULT_MTU;
434 pcb->rx_cred = RFCOMM_DEFAULT_CREDITS;
436 mtx_init(&pcb->pcb_mtx, "btsocks_rfcomm_pcb_mtx", NULL, MTX_DEF);
437 callout_handle_init(&pcb->timo);
439 /* Add the PCB to the list */
440 mtx_lock(&ng_btsocket_rfcomm_sockets_mtx);
441 LIST_INSERT_HEAD(&ng_btsocket_rfcomm_sockets, pcb, next);
442 mtx_unlock(&ng_btsocket_rfcomm_sockets_mtx);
445 } /* ng_btsocket_rfcomm_attach */
452 ng_btsocket_rfcomm_bind(struct socket *so, struct sockaddr *nam,
455 ng_btsocket_rfcomm_pcb_t *pcb = so2rfcomm_pcb(so), *pcb1;
456 struct sockaddr_rfcomm *sa = (struct sockaddr_rfcomm *) nam;
464 if (sa->rfcomm_family != AF_BLUETOOTH)
465 return (EAFNOSUPPORT);
466 if (sa->rfcomm_len != sizeof(*sa))
468 if (sa->rfcomm_channel > 30)
471 mtx_lock(&pcb->pcb_mtx);
473 if (sa->rfcomm_channel != 0) {
474 mtx_lock(&ng_btsocket_rfcomm_sockets_mtx);
476 LIST_FOREACH(pcb1, &ng_btsocket_rfcomm_sockets, next) {
477 if (pcb1->channel == sa->rfcomm_channel &&
478 bcmp(&pcb1->src, &sa->rfcomm_bdaddr,
479 sizeof(pcb1->src)) == 0) {
480 mtx_unlock(&ng_btsocket_rfcomm_sockets_mtx);
481 mtx_unlock(&pcb->pcb_mtx);
487 mtx_unlock(&ng_btsocket_rfcomm_sockets_mtx);
490 bcopy(&sa->rfcomm_bdaddr, &pcb->src, sizeof(pcb->src));
491 pcb->channel = sa->rfcomm_channel;
493 mtx_unlock(&pcb->pcb_mtx);
496 } /* ng_btsocket_rfcomm_bind */
503 ng_btsocket_rfcomm_connect(struct socket *so, struct sockaddr *nam,
506 ng_btsocket_rfcomm_pcb_t *pcb = so2rfcomm_pcb(so);
507 struct sockaddr_rfcomm *sa = (struct sockaddr_rfcomm *) nam;
508 ng_btsocket_rfcomm_session_t *s = NULL;
509 struct socket *l2so = NULL;
518 if (sa->rfcomm_family != AF_BLUETOOTH)
519 return (EAFNOSUPPORT);
520 if (sa->rfcomm_len != sizeof(*sa))
522 if (sa->rfcomm_channel > 30)
524 if (sa->rfcomm_channel == 0 ||
525 bcmp(&sa->rfcomm_bdaddr, NG_HCI_BDADDR_ANY, sizeof(bdaddr_t)) == 0)
526 return (EDESTADDRREQ);
529 * Note that we will not check for errors in socreate() because
530 * if we failed to create L2CAP socket at this point we still
531 * might have already open session.
534 error = socreate(PF_BLUETOOTH, &l2so, SOCK_SEQPACKET,
535 BLUETOOTH_PROTO_L2CAP, td->td_ucred, td);
538 * Look for session between "pcb->src" and "sa->rfcomm_bdaddr" (dst)
541 mtx_lock(&ng_btsocket_rfcomm_sessions_mtx);
543 s = ng_btsocket_rfcomm_session_by_addr(&pcb->src, &sa->rfcomm_bdaddr);
546 * We need to create new RFCOMM session. Check if we have L2CAP
547 * socket. If l2so == NULL then error has the error code from
552 mtx_unlock(&ng_btsocket_rfcomm_sessions_mtx);
556 error = ng_btsocket_rfcomm_session_create(&s, l2so,
557 &pcb->src, &sa->rfcomm_bdaddr, td);
559 mtx_unlock(&ng_btsocket_rfcomm_sessions_mtx);
564 } else if (l2so != NULL)
565 soclose(l2so); /* we don't need new L2CAP socket */
568 * Check if we already have the same DLCI the same session
571 mtx_lock(&s->session_mtx);
572 mtx_lock(&pcb->pcb_mtx);
574 dlci = RFCOMM_MKDLCI(!INITIATOR(s), sa->rfcomm_channel);
576 if (ng_btsocket_rfcomm_pcb_by_dlci(s, dlci) != NULL) {
577 mtx_unlock(&pcb->pcb_mtx);
578 mtx_unlock(&s->session_mtx);
579 mtx_unlock(&ng_btsocket_rfcomm_sessions_mtx);
585 * Check session state and if its not acceptable then refuse connection
589 case NG_BTSOCKET_RFCOMM_SESSION_CONNECTING:
590 case NG_BTSOCKET_RFCOMM_SESSION_CONNECTED:
591 case NG_BTSOCKET_RFCOMM_SESSION_OPEN:
593 * Update destination address and channel and attach
597 bcopy(&sa->rfcomm_bdaddr, &pcb->dst, sizeof(pcb->dst));
598 pcb->channel = sa->rfcomm_channel;
601 LIST_INSERT_HEAD(&s->dlcs, pcb, session_next);
604 ng_btsocket_rfcomm_timeout(pcb);
605 soisconnecting(pcb->so);
607 if (s->state == NG_BTSOCKET_RFCOMM_SESSION_OPEN) {
609 bcopy(&so2l2cap_pcb(s->l2so)->src, &pcb->src,
612 pcb->state = NG_BTSOCKET_RFCOMM_DLC_CONFIGURING;
614 error = ng_btsocket_rfcomm_send_pn(pcb);
616 error = ng_btsocket_rfcomm_task_wakeup();
618 pcb->state = NG_BTSOCKET_RFCOMM_DLC_W4_CONNECT;
626 mtx_unlock(&pcb->pcb_mtx);
627 mtx_unlock(&s->session_mtx);
628 mtx_unlock(&ng_btsocket_rfcomm_sessions_mtx);
631 } /* ng_btsocket_rfcomm_connect */
634 * Process ioctl's calls on socket.
635 * XXX FIXME this should provide interface to the RFCOMM multiplexor channel
639 ng_btsocket_rfcomm_control(struct socket *so, u_long cmd, caddr_t data,
640 struct ifnet *ifp, struct thread *td)
643 } /* ng_btsocket_rfcomm_control */
646 * Process getsockopt/setsockopt system calls
650 ng_btsocket_rfcomm_ctloutput(struct socket *so, struct sockopt *sopt)
652 ng_btsocket_rfcomm_pcb_p pcb = so2rfcomm_pcb(so);
653 struct ng_btsocket_rfcomm_fc_info fcinfo;
658 if (sopt->sopt_level != SOL_RFCOMM)
661 mtx_lock(&pcb->pcb_mtx);
663 switch (sopt->sopt_dir) {
665 switch (sopt->sopt_name) {
667 error = sooptcopyout(sopt, &pcb->mtu, sizeof(pcb->mtu));
670 case SO_RFCOMM_FC_INFO:
671 fcinfo.lmodem = pcb->lmodem;
672 fcinfo.rmodem = pcb->rmodem;
673 fcinfo.tx_cred = pcb->tx_cred;
674 fcinfo.rx_cred = pcb->rx_cred;
675 fcinfo.cfc = (pcb->flags & NG_BTSOCKET_RFCOMM_DLC_CFC)?
679 error = sooptcopyout(sopt, &fcinfo, sizeof(fcinfo));
689 switch (sopt->sopt_name) {
701 mtx_unlock(&pcb->pcb_mtx);
704 } /* ng_btsocket_rfcomm_ctloutput */
707 * Detach and destroy socket
711 ng_btsocket_rfcomm_detach(struct socket *so)
713 ng_btsocket_rfcomm_pcb_p pcb = so2rfcomm_pcb(so);
715 KASSERT(pcb != NULL, ("ng_btsocket_rfcomm_detach: pcb == NULL"));
717 mtx_lock(&pcb->pcb_mtx);
719 switch (pcb->state) {
720 case NG_BTSOCKET_RFCOMM_DLC_W4_CONNECT:
721 case NG_BTSOCKET_RFCOMM_DLC_CONFIGURING:
722 case NG_BTSOCKET_RFCOMM_DLC_CONNECTING:
723 case NG_BTSOCKET_RFCOMM_DLC_CONNECTED:
724 /* XXX What to do with pending request? */
725 if (pcb->flags & NG_BTSOCKET_RFCOMM_DLC_TIMO)
726 ng_btsocket_rfcomm_untimeout(pcb);
728 if (pcb->state == NG_BTSOCKET_RFCOMM_DLC_W4_CONNECT)
729 pcb->flags |= NG_BTSOCKET_RFCOMM_DLC_DETACHED;
731 pcb->state = NG_BTSOCKET_RFCOMM_DLC_DISCONNECTING;
733 ng_btsocket_rfcomm_task_wakeup();
736 case NG_BTSOCKET_RFCOMM_DLC_DISCONNECTING:
737 ng_btsocket_rfcomm_task_wakeup();
741 while (pcb->state != NG_BTSOCKET_RFCOMM_DLC_CLOSED)
742 msleep(&pcb->state, &pcb->pcb_mtx, PZERO, "rf_det", 0);
744 if (pcb->session != NULL)
745 panic("%s: pcb->session != NULL\n", __func__);
746 if (pcb->flags & NG_BTSOCKET_RFCOMM_DLC_TIMO)
747 panic("%s: timeout on closed DLC, flags=%#x\n",
748 __func__, pcb->flags);
750 mtx_lock(&ng_btsocket_rfcomm_sockets_mtx);
751 LIST_REMOVE(pcb, next);
752 mtx_unlock(&ng_btsocket_rfcomm_sockets_mtx);
754 mtx_unlock(&pcb->pcb_mtx);
756 mtx_destroy(&pcb->pcb_mtx);
757 bzero(pcb, sizeof(*pcb));
758 free(pcb, M_NETGRAPH_BTSOCKET_RFCOMM);
760 soisdisconnected(so);
762 } /* ng_btsocket_rfcomm_detach */
769 ng_btsocket_rfcomm_disconnect(struct socket *so)
771 ng_btsocket_rfcomm_pcb_p pcb = so2rfcomm_pcb(so);
776 mtx_lock(&pcb->pcb_mtx);
778 if (pcb->state == NG_BTSOCKET_RFCOMM_DLC_DISCONNECTING) {
779 mtx_unlock(&pcb->pcb_mtx);
780 return (EINPROGRESS);
783 /* XXX What to do with pending request? */
784 if (pcb->flags & NG_BTSOCKET_RFCOMM_DLC_TIMO)
785 ng_btsocket_rfcomm_untimeout(pcb);
787 switch (pcb->state) {
788 case NG_BTSOCKET_RFCOMM_DLC_CONFIGURING: /* XXX can we get here? */
789 case NG_BTSOCKET_RFCOMM_DLC_CONNECTING: /* XXX can we get here? */
790 case NG_BTSOCKET_RFCOMM_DLC_CONNECTED:
793 * Just change DLC state and enqueue RFCOMM task. It will
794 * queue and send DISC on the DLC.
797 pcb->state = NG_BTSOCKET_RFCOMM_DLC_DISCONNECTING;
798 soisdisconnecting(so);
800 ng_btsocket_rfcomm_task_wakeup();
803 case NG_BTSOCKET_RFCOMM_DLC_CLOSED:
804 case NG_BTSOCKET_RFCOMM_DLC_W4_CONNECT:
808 panic("%s: Invalid DLC state=%d, flags=%#x\n",
809 __func__, pcb->state, pcb->flags);
813 mtx_unlock(&pcb->pcb_mtx);
816 } /* ng_btsocket_rfcomm_disconnect */
819 * Listen on socket. First call to listen() will create listening RFCOMM session
823 ng_btsocket_rfcomm_listen(struct socket *so, int backlog, struct thread *td)
825 ng_btsocket_rfcomm_pcb_p pcb = so2rfcomm_pcb(so), pcb1;
826 ng_btsocket_rfcomm_session_p s = NULL;
827 struct socket *l2so = NULL;
828 int error, socreate_error, usedchannels;
832 if (pcb->channel > 30)
833 return (EADDRNOTAVAIL);
837 mtx_lock(&pcb->pcb_mtx);
839 if (pcb->channel == 0) {
840 mtx_lock(&ng_btsocket_rfcomm_sockets_mtx);
842 LIST_FOREACH(pcb1, &ng_btsocket_rfcomm_sockets, next)
843 if (pcb1->channel != 0 &&
844 bcmp(&pcb1->src, &pcb->src, sizeof(pcb->src)) == 0)
845 usedchannels |= (1 << (pcb1->channel - 1));
847 for (pcb->channel = 30; pcb->channel > 0; pcb->channel --)
848 if (!(usedchannels & (1 << (pcb->channel - 1))))
851 if (pcb->channel == 0) {
852 mtx_unlock(&ng_btsocket_rfcomm_sockets_mtx);
853 mtx_unlock(&pcb->pcb_mtx);
855 return (EADDRNOTAVAIL);
858 mtx_unlock(&ng_btsocket_rfcomm_sockets_mtx);
861 mtx_unlock(&pcb->pcb_mtx);
864 * Note that we will not check for errors in socreate() because
865 * if we failed to create L2CAP socket at this point we still
866 * might have already open session.
869 socreate_error = socreate(PF_BLUETOOTH, &l2so, SOCK_SEQPACKET,
870 BLUETOOTH_PROTO_L2CAP, td->td_ucred, td);
873 * Transition the socket and session into the LISTENING state. Check
874 * for collisions first, as there can only be one.
876 mtx_lock(&ng_btsocket_rfcomm_sessions_mtx);
878 error = solisten_proto_check(so);
883 LIST_FOREACH(s, &ng_btsocket_rfcomm_sessions, next)
884 if (s->state == NG_BTSOCKET_RFCOMM_SESSION_LISTENING)
889 * We need to create default RFCOMM session. Check if we have
890 * L2CAP socket. If l2so == NULL then error has the error code
894 error = socreate_error;
899 * Create default listen RFCOMM session. The default RFCOMM
900 * session will listen on ANY address.
902 * XXX FIXME Note that currently there is no way to adjust MTU
903 * for the default session.
905 error = ng_btsocket_rfcomm_session_create(&s, l2so,
906 NG_HCI_BDADDR_ANY, NULL, td);
912 solisten_proto(so, backlog);
915 mtx_unlock(&ng_btsocket_rfcomm_sessions_mtx);
917 * If we still have an l2so reference here, it's unneeded, so release
923 } /* ng_btsocket_listen */
930 ng_btsocket_rfcomm_peeraddr(struct socket *so, struct sockaddr **nam)
932 ng_btsocket_rfcomm_pcb_p pcb = so2rfcomm_pcb(so);
933 struct sockaddr_rfcomm sa;
938 bcopy(&pcb->dst, &sa.rfcomm_bdaddr, sizeof(sa.rfcomm_bdaddr));
939 sa.rfcomm_channel = pcb->channel;
940 sa.rfcomm_len = sizeof(sa);
941 sa.rfcomm_family = AF_BLUETOOTH;
943 *nam = sodupsockaddr((struct sockaddr *) &sa, M_NOWAIT);
945 return ((*nam == NULL)? ENOMEM : 0);
946 } /* ng_btsocket_rfcomm_peeraddr */
949 * Send data to socket
953 ng_btsocket_rfcomm_send(struct socket *so, int flags, struct mbuf *m,
954 struct sockaddr *nam, struct mbuf *control, struct thread *td)
956 ng_btsocket_rfcomm_pcb_t *pcb = so2rfcomm_pcb(so);
959 /* Check socket and input */
960 if (pcb == NULL || m == NULL || control != NULL) {
965 mtx_lock(&pcb->pcb_mtx);
967 /* Make sure DLC is connected */
968 if (pcb->state != NG_BTSOCKET_RFCOMM_DLC_CONNECTED) {
969 mtx_unlock(&pcb->pcb_mtx);
974 /* Put the packet on the socket's send queue and wakeup RFCOMM task */
975 sbappend(&pcb->so->so_snd, m);
978 if (!(pcb->flags & NG_BTSOCKET_RFCOMM_DLC_SENDING)) {
979 pcb->flags |= NG_BTSOCKET_RFCOMM_DLC_SENDING;
980 error = ng_btsocket_rfcomm_task_wakeup();
983 mtx_unlock(&pcb->pcb_mtx);
985 NG_FREE_M(m); /* checks for != NULL */
989 } /* ng_btsocket_rfcomm_send */
996 ng_btsocket_rfcomm_sockaddr(struct socket *so, struct sockaddr **nam)
998 ng_btsocket_rfcomm_pcb_p pcb = so2rfcomm_pcb(so);
999 struct sockaddr_rfcomm sa;
1004 bcopy(&pcb->src, &sa.rfcomm_bdaddr, sizeof(sa.rfcomm_bdaddr));
1005 sa.rfcomm_channel = pcb->channel;
1006 sa.rfcomm_len = sizeof(sa);
1007 sa.rfcomm_family = AF_BLUETOOTH;
1009 *nam = sodupsockaddr((struct sockaddr *) &sa, M_NOWAIT);
1011 return ((*nam == NULL)? ENOMEM : 0);
1012 } /* ng_btsocket_rfcomm_sockaddr */
1015 * Upcall function for L2CAP sockets. Enqueue RFCOMM task.
1019 ng_btsocket_rfcomm_upcall(struct socket *so, void *arg, int waitflag)
1024 panic("%s: so == NULL\n", __func__);
1026 if ((error = ng_btsocket_rfcomm_task_wakeup()) != 0)
1027 NG_BTSOCKET_RFCOMM_ALERT(
1028 "%s: Could not enqueue RFCOMM task, error=%d\n", __func__, error);
1030 } /* ng_btsocket_rfcomm_upcall */
1033 * RFCOMM task. Will handle all RFCOMM sessions in one pass.
1034 * XXX FIXME does not scale very well
1038 ng_btsocket_rfcomm_sessions_task(void *ctx, int pending)
1040 ng_btsocket_rfcomm_session_p s = NULL, s_next = NULL;
1042 mtx_lock(&ng_btsocket_rfcomm_sessions_mtx);
1044 for (s = LIST_FIRST(&ng_btsocket_rfcomm_sessions); s != NULL; ) {
1045 mtx_lock(&s->session_mtx);
1046 s_next = LIST_NEXT(s, next);
1048 ng_btsocket_rfcomm_session_task(s);
1050 if (s->state == NG_BTSOCKET_RFCOMM_SESSION_CLOSED) {
1051 /* Unlink and clean the session */
1052 LIST_REMOVE(s, next);
1054 NG_BT_MBUFQ_DRAIN(&s->outq);
1055 if (!LIST_EMPTY(&s->dlcs))
1056 panic("%s: DLC list is not empty\n", __func__);
1058 /* Close L2CAP socket */
1059 SOCKBUF_LOCK(&s->l2so->so_rcv);
1060 soupcall_clear(s->l2so, SO_RCV);
1061 SOCKBUF_UNLOCK(&s->l2so->so_rcv);
1062 SOCKBUF_LOCK(&s->l2so->so_snd);
1063 soupcall_clear(s->l2so, SO_SND);
1064 SOCKBUF_UNLOCK(&s->l2so->so_snd);
1067 mtx_unlock(&s->session_mtx);
1069 mtx_destroy(&s->session_mtx);
1070 bzero(s, sizeof(*s));
1071 free(s, M_NETGRAPH_BTSOCKET_RFCOMM);
1073 mtx_unlock(&s->session_mtx);
1078 mtx_unlock(&ng_btsocket_rfcomm_sessions_mtx);
1079 } /* ng_btsocket_rfcomm_sessions_task */
1082 * Process RFCOMM session. Will handle all RFCOMM sockets in one pass.
1086 ng_btsocket_rfcomm_session_task(ng_btsocket_rfcomm_session_p s)
1088 mtx_assert(&s->session_mtx, MA_OWNED);
1090 if (s->l2so->so_rcv.sb_state & SBS_CANTRCVMORE) {
1091 NG_BTSOCKET_RFCOMM_INFO(
1092 "%s: L2CAP connection has been terminated, so=%p, so_state=%#x, so_count=%d, " \
1093 "state=%d, flags=%#x\n", __func__, s->l2so, s->l2so->so_state,
1094 s->l2so->so_count, s->state, s->flags);
1096 s->state = NG_BTSOCKET_RFCOMM_SESSION_CLOSED;
1097 ng_btsocket_rfcomm_session_clean(s);
1100 /* Now process upcall */
1102 /* Try to accept new L2CAP connection(s) */
1103 case NG_BTSOCKET_RFCOMM_SESSION_LISTENING:
1104 while (ng_btsocket_rfcomm_session_accept(s) == 0)
1108 /* Process the results of the L2CAP connect */
1109 case NG_BTSOCKET_RFCOMM_SESSION_CONNECTING:
1110 ng_btsocket_rfcomm_session_process_pcb(s);
1112 if (ng_btsocket_rfcomm_session_connect(s) != 0) {
1113 s->state = NG_BTSOCKET_RFCOMM_SESSION_CLOSED;
1114 ng_btsocket_rfcomm_session_clean(s);
1118 /* Try to receive/send more data */
1119 case NG_BTSOCKET_RFCOMM_SESSION_CONNECTED:
1120 case NG_BTSOCKET_RFCOMM_SESSION_OPEN:
1121 case NG_BTSOCKET_RFCOMM_SESSION_DISCONNECTING:
1122 ng_btsocket_rfcomm_session_process_pcb(s);
1124 if (ng_btsocket_rfcomm_session_receive(s) != 0) {
1125 s->state = NG_BTSOCKET_RFCOMM_SESSION_CLOSED;
1126 ng_btsocket_rfcomm_session_clean(s);
1127 } else if (ng_btsocket_rfcomm_session_send(s) != 0) {
1128 s->state = NG_BTSOCKET_RFCOMM_SESSION_CLOSED;
1129 ng_btsocket_rfcomm_session_clean(s);
1133 case NG_BTSOCKET_RFCOMM_SESSION_CLOSED:
1137 panic("%s: Invalid session state=%d, flags=%#x\n",
1138 __func__, s->state, s->flags);
1141 } /* ng_btsocket_rfcomm_session_task */
1144 * Process RFCOMM connection indicator. Caller must hold s->session_mtx
1147 static ng_btsocket_rfcomm_pcb_p
1148 ng_btsocket_rfcomm_connect_ind(ng_btsocket_rfcomm_session_p s, int channel)
1150 ng_btsocket_rfcomm_pcb_p pcb = NULL, pcb1 = NULL;
1151 ng_btsocket_l2cap_pcb_p l2pcb = NULL;
1152 struct socket *so1 = NULL;
1154 mtx_assert(&s->session_mtx, MA_OWNED);
1157 * Try to find RFCOMM socket that listens on given source address
1158 * and channel. This will return the best possible match.
1161 l2pcb = so2l2cap_pcb(s->l2so);
1162 pcb = ng_btsocket_rfcomm_pcb_listener(&l2pcb->src, channel);
1167 * Check the pending connections queue and if we have space then
1168 * create new socket and set proper source and destination address,
1172 mtx_lock(&pcb->pcb_mtx);
1174 if (pcb->so->so_qlen <= pcb->so->so_qlimit) {
1175 CURVNET_SET(pcb->so->so_vnet);
1176 so1 = sonewconn(pcb->so, 0);
1180 mtx_unlock(&pcb->pcb_mtx);
1186 * If we got here than we have created new socket. So complete the
1187 * connection. Set source and destination address from the session.
1190 pcb1 = so2rfcomm_pcb(so1);
1192 panic("%s: pcb1 == NULL\n", __func__);
1194 mtx_lock(&pcb1->pcb_mtx);
1196 bcopy(&l2pcb->src, &pcb1->src, sizeof(pcb1->src));
1197 bcopy(&l2pcb->dst, &pcb1->dst, sizeof(pcb1->dst));
1198 pcb1->channel = channel;
1200 /* Link new DLC to the session. We already hold s->session_mtx */
1201 LIST_INSERT_HEAD(&s->dlcs, pcb1, session_next);
1204 mtx_unlock(&pcb1->pcb_mtx);
1207 } /* ng_btsocket_rfcomm_connect_ind */
1210 * Process RFCOMM connect confirmation. Caller must hold s->session_mtx.
1214 ng_btsocket_rfcomm_connect_cfm(ng_btsocket_rfcomm_session_p s)
1216 ng_btsocket_rfcomm_pcb_p pcb = NULL, pcb_next = NULL;
1219 mtx_assert(&s->session_mtx, MA_OWNED);
1222 * Wake up all waiting sockets and send PN request for each of them.
1223 * Note that timeout already been set in ng_btsocket_rfcomm_connect()
1225 * Note: cannot use LIST_FOREACH because ng_btsocket_rfcomm_pcb_kill
1226 * will unlink DLC from the session
1229 for (pcb = LIST_FIRST(&s->dlcs); pcb != NULL; ) {
1230 mtx_lock(&pcb->pcb_mtx);
1231 pcb_next = LIST_NEXT(pcb, session_next);
1233 if (pcb->state == NG_BTSOCKET_RFCOMM_DLC_W4_CONNECT) {
1235 bcopy(&so2l2cap_pcb(s->l2so)->src, &pcb->src,
1238 error = ng_btsocket_rfcomm_send_pn(pcb);
1240 pcb->state = NG_BTSOCKET_RFCOMM_DLC_CONFIGURING;
1242 ng_btsocket_rfcomm_pcb_kill(pcb, error);
1245 mtx_unlock(&pcb->pcb_mtx);
1248 } /* ng_btsocket_rfcomm_connect_cfm */
1250 /*****************************************************************************
1251 *****************************************************************************
1253 *****************************************************************************
1254 *****************************************************************************/
1257 * Create new RFCOMM session. That function WILL NOT take ownership over l2so.
1258 * Caller MUST free l2so if function failed.
1262 ng_btsocket_rfcomm_session_create(ng_btsocket_rfcomm_session_p *sp,
1263 struct socket *l2so, bdaddr_p src, bdaddr_p dst,
1266 ng_btsocket_rfcomm_session_p s = NULL;
1267 struct sockaddr_l2cap l2sa;
1268 struct sockopt l2sopt;
1272 mtx_assert(&ng_btsocket_rfcomm_sessions_mtx, MA_OWNED);
1274 /* Allocate the RFCOMM session */
1275 s = malloc(sizeof(*s),
1276 M_NETGRAPH_BTSOCKET_RFCOMM, M_NOWAIT | M_ZERO);
1281 s->mtu = RFCOMM_DEFAULT_MTU;
1283 s->state = NG_BTSOCKET_RFCOMM_SESSION_CLOSED;
1284 NG_BT_MBUFQ_INIT(&s->outq, ifqmaxlen);
1287 * XXX Mark session mutex as DUPOK to prevent "duplicated lock of
1288 * the same type" message. When accepting new L2CAP connection
1289 * ng_btsocket_rfcomm_session_accept() holds both session mutexes
1290 * for "old" (accepting) session and "new" (created) session.
1293 mtx_init(&s->session_mtx, "btsocks_rfcomm_session_mtx", NULL,
1296 LIST_INIT(&s->dlcs);
1298 /* Prepare L2CAP socket */
1299 SOCKBUF_LOCK(&l2so->so_rcv);
1300 soupcall_set(l2so, SO_RCV, ng_btsocket_rfcomm_upcall, NULL);
1301 SOCKBUF_UNLOCK(&l2so->so_rcv);
1302 SOCKBUF_LOCK(&l2so->so_snd);
1303 soupcall_set(l2so, SO_SND, ng_btsocket_rfcomm_upcall, NULL);
1304 SOCKBUF_UNLOCK(&l2so->so_snd);
1305 l2so->so_state |= SS_NBIO;
1308 mtx_lock(&s->session_mtx);
1311 * "src" == NULL and "dst" == NULL means just create session.
1312 * caller must do the rest
1315 if (src == NULL && dst == NULL)
1319 * Set incoming MTU on L2CAP socket. It is RFCOMM session default MTU
1320 * plus 5 bytes: RFCOMM frame header, one extra byte for length and one
1321 * extra byte for credits.
1324 mtu = s->mtu + sizeof(struct rfcomm_frame_hdr) + 1 + 1;
1326 l2sopt.sopt_dir = SOPT_SET;
1327 l2sopt.sopt_level = SOL_L2CAP;
1328 l2sopt.sopt_name = SO_L2CAP_IMTU;
1329 l2sopt.sopt_val = (void *) &mtu;
1330 l2sopt.sopt_valsize = sizeof(mtu);
1331 l2sopt.sopt_td = NULL;
1333 error = sosetopt(s->l2so, &l2sopt);
1337 /* Bind socket to "src" address */
1338 l2sa.l2cap_len = sizeof(l2sa);
1339 l2sa.l2cap_family = AF_BLUETOOTH;
1340 l2sa.l2cap_psm = (dst == NULL)? htole16(NG_L2CAP_PSM_RFCOMM) : 0;
1341 bcopy(src, &l2sa.l2cap_bdaddr, sizeof(l2sa.l2cap_bdaddr));
1343 error = sobind(s->l2so, (struct sockaddr *) &l2sa, td);
1347 /* If "dst" is not NULL then initiate connect(), otherwise listen() */
1350 s->state = NG_BTSOCKET_RFCOMM_SESSION_LISTENING;
1352 error = solisten(s->l2so, 10, td);
1356 s->flags = NG_BTSOCKET_RFCOMM_SESSION_INITIATOR;
1357 s->state = NG_BTSOCKET_RFCOMM_SESSION_CONNECTING;
1359 l2sa.l2cap_len = sizeof(l2sa);
1360 l2sa.l2cap_family = AF_BLUETOOTH;
1361 l2sa.l2cap_psm = htole16(NG_L2CAP_PSM_RFCOMM);
1362 bcopy(dst, &l2sa.l2cap_bdaddr, sizeof(l2sa.l2cap_bdaddr));
1364 error = soconnect(s->l2so, (struct sockaddr *) &l2sa, td);
1370 LIST_INSERT_HEAD(&ng_btsocket_rfcomm_sessions, s, next);
1373 mtx_unlock(&s->session_mtx);
1378 mtx_unlock(&s->session_mtx);
1380 /* Return L2CAP socket back to its original state */
1381 SOCKBUF_LOCK(&l2so->so_rcv);
1382 soupcall_clear(s->l2so, SO_RCV);
1383 SOCKBUF_UNLOCK(&l2so->so_rcv);
1384 SOCKBUF_LOCK(&l2so->so_snd);
1385 soupcall_clear(s->l2so, SO_SND);
1386 SOCKBUF_UNLOCK(&l2so->so_snd);
1387 l2so->so_state &= ~SS_NBIO;
1389 mtx_destroy(&s->session_mtx);
1390 bzero(s, sizeof(*s));
1391 free(s, M_NETGRAPH_BTSOCKET_RFCOMM);
1394 } /* ng_btsocket_rfcomm_session_create */
1397 * Process accept() on RFCOMM session
1398 * XXX FIXME locking for "l2so"?
1402 ng_btsocket_rfcomm_session_accept(ng_btsocket_rfcomm_session_p s0)
1404 struct socket *l2so = NULL;
1405 struct sockaddr_l2cap *l2sa = NULL;
1406 ng_btsocket_l2cap_pcb_t *l2pcb = NULL;
1407 ng_btsocket_rfcomm_session_p s = NULL;
1410 mtx_assert(&ng_btsocket_rfcomm_sessions_mtx, MA_OWNED);
1411 mtx_assert(&s0->session_mtx, MA_OWNED);
1413 /* Check if there is a complete L2CAP connection in the queue */
1414 if ((error = s0->l2so->so_error) != 0) {
1415 NG_BTSOCKET_RFCOMM_ERR(
1416 "%s: Could not accept connection on L2CAP socket, error=%d\n", __func__, error);
1417 s0->l2so->so_error = 0;
1423 if (TAILQ_EMPTY(&s0->l2so->so_comp)) {
1425 if (s0->l2so->so_rcv.sb_state & SBS_CANTRCVMORE)
1426 return (ECONNABORTED);
1427 return (EWOULDBLOCK);
1430 /* Accept incoming L2CAP connection */
1431 l2so = TAILQ_FIRST(&s0->l2so->so_comp);
1433 panic("%s: l2so == NULL\n", __func__);
1435 TAILQ_REMOVE(&s0->l2so->so_comp, l2so, so_list);
1436 s0->l2so->so_qlen --;
1437 l2so->so_qstate &= ~SQ_COMP;
1438 l2so->so_head = NULL;
1441 l2so->so_state |= SS_NBIO;
1445 error = soaccept(l2so, (struct sockaddr **) &l2sa);
1447 NG_BTSOCKET_RFCOMM_ERR(
1448 "%s: soaccept() on L2CAP socket failed, error=%d\n", __func__, error);
1455 * Check if there is already active RFCOMM session between two devices.
1456 * If so then close L2CAP connection. We only support one RFCOMM session
1457 * between each pair of devices. Note that here we assume session in any
1458 * state. The session even could be in the middle of disconnecting.
1461 l2pcb = so2l2cap_pcb(l2so);
1462 s = ng_btsocket_rfcomm_session_by_addr(&l2pcb->src, &l2pcb->dst);
1464 /* Create a new RFCOMM session */
1465 error = ng_btsocket_rfcomm_session_create(&s, l2so, NULL, NULL,
1466 curthread /* XXX */);
1468 mtx_lock(&s->session_mtx);
1471 s->state = NG_BTSOCKET_RFCOMM_SESSION_CONNECTED;
1474 * Adjust MTU on incomming connection. Reserve 5 bytes:
1475 * RFCOMM frame header, one extra byte for length and
1476 * one extra byte for credits.
1479 s->mtu = min(l2pcb->imtu, l2pcb->omtu) -
1480 sizeof(struct rfcomm_frame_hdr) - 1 - 1;
1482 mtx_unlock(&s->session_mtx);
1484 NG_BTSOCKET_RFCOMM_ALERT(
1485 "%s: Failed to create new RFCOMM session, error=%d\n", __func__, error);
1490 NG_BTSOCKET_RFCOMM_WARN(
1491 "%s: Rejecting duplicating RFCOMM session between src=%x:%x:%x:%x:%x:%x and " \
1492 "dst=%x:%x:%x:%x:%x:%x, state=%d, flags=%#x\n", __func__,
1493 l2pcb->src.b[5], l2pcb->src.b[4], l2pcb->src.b[3],
1494 l2pcb->src.b[2], l2pcb->src.b[1], l2pcb->src.b[0],
1495 l2pcb->dst.b[5], l2pcb->dst.b[4], l2pcb->dst.b[3],
1496 l2pcb->dst.b[2], l2pcb->dst.b[1], l2pcb->dst.b[0],
1497 s->state, s->flags);
1504 } /* ng_btsocket_rfcomm_session_accept */
1507 * Process connect() on RFCOMM session
1508 * XXX FIXME locking for "l2so"?
1512 ng_btsocket_rfcomm_session_connect(ng_btsocket_rfcomm_session_p s)
1514 ng_btsocket_l2cap_pcb_p l2pcb = so2l2cap_pcb(s->l2so);
1517 mtx_assert(&s->session_mtx, MA_OWNED);
1519 /* First check if connection has failed */
1520 if ((error = s->l2so->so_error) != 0) {
1521 s->l2so->so_error = 0;
1523 NG_BTSOCKET_RFCOMM_ERR(
1524 "%s: Could not connect RFCOMM session, error=%d, state=%d, flags=%#x\n",
1525 __func__, error, s->state, s->flags);
1530 /* Is connection still in progress? */
1531 if (s->l2so->so_state & SS_ISCONNECTING)
1535 * If we got here then we are connected. Send SABM on DLCI 0 to
1536 * open multiplexor channel.
1540 s->state = NG_BTSOCKET_RFCOMM_SESSION_CONNECTED;
1543 * Adjust MTU on outgoing connection. Reserve 5 bytes: RFCOMM
1544 * frame header, one extra byte for length and one extra byte
1548 s->mtu = min(l2pcb->imtu, l2pcb->omtu) -
1549 sizeof(struct rfcomm_frame_hdr) - 1 - 1;
1551 error = ng_btsocket_rfcomm_send_command(s,RFCOMM_FRAME_SABM,0);
1553 error = ng_btsocket_rfcomm_task_wakeup();
1557 }/* ng_btsocket_rfcomm_session_connect */
1560 * Receive data on RFCOMM session
1561 * XXX FIXME locking for "l2so"?
1565 ng_btsocket_rfcomm_session_receive(ng_btsocket_rfcomm_session_p s)
1567 struct mbuf *m = NULL;
1569 int more, flags, error;
1571 mtx_assert(&s->session_mtx, MA_OWNED);
1573 /* Can we read from the L2CAP socket? */
1574 if (!soreadable(s->l2so))
1577 /* First check for error on L2CAP socket */
1578 if ((error = s->l2so->so_error) != 0) {
1579 s->l2so->so_error = 0;
1581 NG_BTSOCKET_RFCOMM_ERR(
1582 "%s: Could not receive data from L2CAP socket, error=%d, state=%d, flags=%#x\n",
1583 __func__, error, s->state, s->flags);
1589 * Read all packets from the L2CAP socket.
1590 * XXX FIXME/VERIFY is that correct? For now use m->m_nextpkt as
1591 * indication that there is more packets on the socket's buffer.
1592 * Also what should we use in uio.uio_resid?
1593 * May be s->mtu + sizeof(struct rfcomm_frame_hdr) + 1 + 1?
1596 for (more = 1; more; ) {
1597 /* Try to get next packet from socket */
1598 bzero(&uio, sizeof(uio));
1599 /* uio.uio_td = NULL; */
1600 uio.uio_resid = 1000000000;
1601 flags = MSG_DONTWAIT;
1604 error = soreceive(s->l2so, NULL, &uio, &m,
1605 (struct mbuf **) NULL, &flags);
1607 if (error == EWOULDBLOCK)
1608 return (0); /* XXX can happen? */
1610 NG_BTSOCKET_RFCOMM_ERR(
1611 "%s: Could not receive data from L2CAP socket, error=%d\n", __func__, error);
1616 more = (m->m_nextpkt != NULL);
1617 m->m_nextpkt = NULL;
1619 ng_btsocket_rfcomm_receive_frame(s, m);
1623 } /* ng_btsocket_rfcomm_session_receive */
1626 * Send data on RFCOMM session
1627 * XXX FIXME locking for "l2so"?
1631 ng_btsocket_rfcomm_session_send(ng_btsocket_rfcomm_session_p s)
1633 struct mbuf *m = NULL;
1636 mtx_assert(&s->session_mtx, MA_OWNED);
1638 /* Send as much as we can from the session queue */
1639 while (sowriteable(s->l2so)) {
1640 /* Check if socket still OK */
1641 if ((error = s->l2so->so_error) != 0) {
1642 s->l2so->so_error = 0;
1644 NG_BTSOCKET_RFCOMM_ERR(
1645 "%s: Detected error=%d on L2CAP socket, state=%d, flags=%#x\n",
1646 __func__, error, s->state, s->flags);
1651 NG_BT_MBUFQ_DEQUEUE(&s->outq, m);
1653 return (0); /* we are done */
1655 /* Call send function on the L2CAP socket */
1656 error = (*s->l2so->so_proto->pr_usrreqs->pru_send)(s->l2so,
1657 0, m, NULL, NULL, curthread /* XXX */);
1659 NG_BTSOCKET_RFCOMM_ERR(
1660 "%s: Could not send data to L2CAP socket, error=%d\n", __func__, error);
1667 } /* ng_btsocket_rfcomm_session_send */
1670 * Close and disconnect all DLCs for the given session. Caller must hold
1671 * s->sesson_mtx. Will wakeup session.
1675 ng_btsocket_rfcomm_session_clean(ng_btsocket_rfcomm_session_p s)
1677 ng_btsocket_rfcomm_pcb_p pcb = NULL, pcb_next = NULL;
1680 mtx_assert(&s->session_mtx, MA_OWNED);
1683 * Note: cannot use LIST_FOREACH because ng_btsocket_rfcomm_pcb_kill
1684 * will unlink DLC from the session
1687 for (pcb = LIST_FIRST(&s->dlcs); pcb != NULL; ) {
1688 mtx_lock(&pcb->pcb_mtx);
1689 pcb_next = LIST_NEXT(pcb, session_next);
1691 NG_BTSOCKET_RFCOMM_INFO(
1692 "%s: Disconnecting dlci=%d, state=%d, flags=%#x\n",
1693 __func__, pcb->dlci, pcb->state, pcb->flags);
1695 if (pcb->state == NG_BTSOCKET_RFCOMM_DLC_CONNECTED)
1698 error = ECONNREFUSED;
1700 ng_btsocket_rfcomm_pcb_kill(pcb, error);
1702 mtx_unlock(&pcb->pcb_mtx);
1705 } /* ng_btsocket_rfcomm_session_clean */
1708 * Process all DLCs on the session. Caller MUST hold s->session_mtx.
1712 ng_btsocket_rfcomm_session_process_pcb(ng_btsocket_rfcomm_session_p s)
1714 ng_btsocket_rfcomm_pcb_p pcb = NULL, pcb_next = NULL;
1717 mtx_assert(&s->session_mtx, MA_OWNED);
1720 * Note: cannot use LIST_FOREACH because ng_btsocket_rfcomm_pcb_kill
1721 * will unlink DLC from the session
1724 for (pcb = LIST_FIRST(&s->dlcs); pcb != NULL; ) {
1725 mtx_lock(&pcb->pcb_mtx);
1726 pcb_next = LIST_NEXT(pcb, session_next);
1728 switch (pcb->state) {
1731 * If DLC in W4_CONNECT state then we should check for both
1732 * timeout and detach.
1735 case NG_BTSOCKET_RFCOMM_DLC_W4_CONNECT:
1736 if (pcb->flags & NG_BTSOCKET_RFCOMM_DLC_DETACHED)
1737 ng_btsocket_rfcomm_pcb_kill(pcb, 0);
1738 else if (pcb->flags & NG_BTSOCKET_RFCOMM_DLC_TIMEDOUT)
1739 ng_btsocket_rfcomm_pcb_kill(pcb, ETIMEDOUT);
1743 * If DLC in CONFIGURING or CONNECTING state then we only
1744 * should check for timeout. If detach() was called then
1745 * DLC will be moved into DISCONNECTING state.
1748 case NG_BTSOCKET_RFCOMM_DLC_CONFIGURING:
1749 case NG_BTSOCKET_RFCOMM_DLC_CONNECTING:
1750 if (pcb->flags & NG_BTSOCKET_RFCOMM_DLC_TIMEDOUT)
1751 ng_btsocket_rfcomm_pcb_kill(pcb, ETIMEDOUT);
1755 * If DLC in CONNECTED state then we need to send data (if any)
1756 * from the socket's send queue. Note that we will send data
1757 * from either all sockets or none. This may overload session's
1758 * outgoing queue (but we do not check for that).
1760 * XXX FIXME need scheduler for RFCOMM sockets
1763 case NG_BTSOCKET_RFCOMM_DLC_CONNECTED:
1764 error = ng_btsocket_rfcomm_pcb_send(pcb, ALOT);
1766 ng_btsocket_rfcomm_pcb_kill(pcb, error);
1770 * If DLC in DISCONNECTING state then we must send DISC frame.
1771 * Note that if DLC has timeout set then we do not need to
1772 * resend DISC frame.
1774 * XXX FIXME need to drain all data from the socket's queue
1775 * if LINGER option was set
1778 case NG_BTSOCKET_RFCOMM_DLC_DISCONNECTING:
1779 if (!(pcb->flags & NG_BTSOCKET_RFCOMM_DLC_TIMO)) {
1780 error = ng_btsocket_rfcomm_send_command(
1781 pcb->session, RFCOMM_FRAME_DISC,
1784 ng_btsocket_rfcomm_timeout(pcb);
1786 ng_btsocket_rfcomm_pcb_kill(pcb, error);
1787 } else if (pcb->flags & NG_BTSOCKET_RFCOMM_DLC_TIMEDOUT)
1788 ng_btsocket_rfcomm_pcb_kill(pcb, ETIMEDOUT);
1791 /* case NG_BTSOCKET_RFCOMM_DLC_CLOSED: */
1793 panic("%s: Invalid DLC state=%d, flags=%#x\n",
1794 __func__, pcb->state, pcb->flags);
1798 mtx_unlock(&pcb->pcb_mtx);
1801 } /* ng_btsocket_rfcomm_session_process_pcb */
1804 * Find RFCOMM session between "src" and "dst".
1805 * Caller MUST hold ng_btsocket_rfcomm_sessions_mtx.
1808 static ng_btsocket_rfcomm_session_p
1809 ng_btsocket_rfcomm_session_by_addr(bdaddr_p src, bdaddr_p dst)
1811 ng_btsocket_rfcomm_session_p s = NULL;
1812 ng_btsocket_l2cap_pcb_p l2pcb = NULL;
1815 mtx_assert(&ng_btsocket_rfcomm_sessions_mtx, MA_OWNED);
1817 any_src = (bcmp(src, NG_HCI_BDADDR_ANY, sizeof(*src)) == 0);
1819 LIST_FOREACH(s, &ng_btsocket_rfcomm_sessions, next) {
1820 l2pcb = so2l2cap_pcb(s->l2so);
1822 if ((any_src || bcmp(&l2pcb->src, src, sizeof(*src)) == 0) &&
1823 bcmp(&l2pcb->dst, dst, sizeof(*dst)) == 0)
1828 } /* ng_btsocket_rfcomm_session_by_addr */
1830 /*****************************************************************************
1831 *****************************************************************************
1833 *****************************************************************************
1834 *****************************************************************************/
1837 * Process incoming RFCOMM frame. Caller must hold s->session_mtx.
1838 * XXX FIXME check frame length
1842 ng_btsocket_rfcomm_receive_frame(ng_btsocket_rfcomm_session_p s,
1845 struct rfcomm_frame_hdr *hdr = NULL;
1846 struct mbuf *m = NULL;
1848 u_int8_t dlci, type;
1851 mtx_assert(&s->session_mtx, MA_OWNED);
1853 /* Pullup as much as we can into first mbuf (for direct access) */
1854 length = min(m0->m_pkthdr.len, MHLEN);
1855 if (m0->m_len < length) {
1856 if ((m0 = m_pullup(m0, length)) == NULL) {
1857 NG_BTSOCKET_RFCOMM_ALERT(
1858 "%s: m_pullup(%d) failed\n", __func__, length);
1864 hdr = mtod(m0, struct rfcomm_frame_hdr *);
1865 dlci = RFCOMM_DLCI(hdr->address);
1866 type = RFCOMM_TYPE(hdr->control);
1868 /* Test EA bit in length. If not set then we have 2 bytes of length */
1869 if (!RFCOMM_EA(hdr->length)) {
1870 bcopy(&hdr->length, &length, sizeof(length));
1871 length = le16toh(length) >> 1;
1872 m_adj(m0, sizeof(*hdr) + 1);
1874 length = hdr->length >> 1;
1875 m_adj(m0, sizeof(*hdr));
1878 NG_BTSOCKET_RFCOMM_INFO(
1879 "%s: Got frame type=%#x, dlci=%d, length=%d, cr=%d, pf=%d, len=%d\n",
1880 __func__, type, dlci, length, RFCOMM_CR(hdr->address),
1881 RFCOMM_PF(hdr->control), m0->m_pkthdr.len);
1884 * Get FCS (the last byte in the frame)
1885 * XXX this will not work if mbuf chain ends with empty mbuf.
1886 * XXX let's hope it never happens :)
1889 for (m = m0; m->m_next != NULL; m = m->m_next)
1892 panic("%s: Empty mbuf at the end of the chain, len=%d\n",
1893 __func__, m->m_len);
1896 * Check FCS. We only need to calculate FCS on first 2 or 3 bytes
1897 * and already m_pullup'ed mbuf chain, so it should be safe.
1900 if (ng_btsocket_rfcomm_check_fcs((u_int8_t *) hdr, type, m->m_data[m->m_len - 1])) {
1901 NG_BTSOCKET_RFCOMM_ERR(
1902 "%s: Invalid RFCOMM packet. Bad checksum\n", __func__);
1908 m_adj(m0, -1); /* Trim FCS byte */
1911 * Process RFCOMM frame.
1913 * From TS 07.10 spec
1915 * "... In the case where a SABM or DISC command with the P bit set
1916 * to 0 is received then the received frame shall be discarded..."
1918 * "... If a unsolicited DM response is received then the frame shall
1919 * be processed irrespective of the P/F setting... "
1921 * "... The station may transmit response frames with the F bit set
1922 * to 0 at any opportunity on an asynchronous basis. However, in the
1923 * case where a UA response is received with the F bit set to 0 then
1924 * the received frame shall be discarded..."
1926 * From Bluetooth spec
1928 * "... When credit based flow control is being used, the meaning of
1929 * the P/F bit in the control field of the RFCOMM header is redefined
1930 * for UIH frames..."
1934 case RFCOMM_FRAME_SABM:
1935 if (RFCOMM_PF(hdr->control))
1936 error = ng_btsocket_rfcomm_receive_sabm(s, dlci);
1939 case RFCOMM_FRAME_DISC:
1940 if (RFCOMM_PF(hdr->control))
1941 error = ng_btsocket_rfcomm_receive_disc(s, dlci);
1944 case RFCOMM_FRAME_UA:
1945 if (RFCOMM_PF(hdr->control))
1946 error = ng_btsocket_rfcomm_receive_ua(s, dlci);
1949 case RFCOMM_FRAME_DM:
1950 error = ng_btsocket_rfcomm_receive_dm(s, dlci);
1953 case RFCOMM_FRAME_UIH:
1955 error = ng_btsocket_rfcomm_receive_mcc(s, m0);
1957 error = ng_btsocket_rfcomm_receive_uih(s, dlci,
1958 RFCOMM_PF(hdr->control), m0);
1964 NG_BTSOCKET_RFCOMM_ERR(
1965 "%s: Invalid RFCOMM packet. Unknown type=%#x\n", __func__, type);
1973 } /* ng_btsocket_rfcomm_receive_frame */
1976 * Process RFCOMM SABM frame
1980 ng_btsocket_rfcomm_receive_sabm(ng_btsocket_rfcomm_session_p s, int dlci)
1982 ng_btsocket_rfcomm_pcb_p pcb = NULL;
1985 mtx_assert(&s->session_mtx, MA_OWNED);
1987 NG_BTSOCKET_RFCOMM_INFO(
1988 "%s: Got SABM, session state=%d, flags=%#x, mtu=%d, dlci=%d\n",
1989 __func__, s->state, s->flags, s->mtu, dlci);
1991 /* DLCI == 0 means open multiplexor channel */
1994 case NG_BTSOCKET_RFCOMM_SESSION_CONNECTED:
1995 case NG_BTSOCKET_RFCOMM_SESSION_OPEN:
1996 error = ng_btsocket_rfcomm_send_command(s,
1997 RFCOMM_FRAME_UA, dlci);
1999 s->state = NG_BTSOCKET_RFCOMM_SESSION_OPEN;
2000 ng_btsocket_rfcomm_connect_cfm(s);
2002 s->state = NG_BTSOCKET_RFCOMM_SESSION_CLOSED;
2003 ng_btsocket_rfcomm_session_clean(s);
2008 NG_BTSOCKET_RFCOMM_WARN(
2009 "%s: Got SABM for session in invalid state state=%d, flags=%#x\n",
2010 __func__, s->state, s->flags);
2018 /* Make sure multiplexor channel is open */
2019 if (s->state != NG_BTSOCKET_RFCOMM_SESSION_OPEN) {
2020 NG_BTSOCKET_RFCOMM_ERR(
2021 "%s: Got SABM for dlci=%d with mulitplexor channel closed, state=%d, " \
2022 "flags=%#x\n", __func__, dlci, s->state, s->flags);
2028 * Check if we have this DLCI. This might happen when remote
2029 * peer uses PN command before actual open (SABM) happens.
2032 pcb = ng_btsocket_rfcomm_pcb_by_dlci(s, dlci);
2034 mtx_lock(&pcb->pcb_mtx);
2036 if (pcb->state != NG_BTSOCKET_RFCOMM_DLC_CONNECTING) {
2037 NG_BTSOCKET_RFCOMM_ERR(
2038 "%s: Got SABM for dlci=%d in invalid state=%d, flags=%#x\n",
2039 __func__, dlci, pcb->state, pcb->flags);
2040 mtx_unlock(&pcb->pcb_mtx);
2045 ng_btsocket_rfcomm_untimeout(pcb);
2047 error = ng_btsocket_rfcomm_send_command(s,RFCOMM_FRAME_UA,dlci);
2049 error = ng_btsocket_rfcomm_send_msc(pcb);
2052 pcb->state = NG_BTSOCKET_RFCOMM_DLC_CONNECTED;
2053 soisconnected(pcb->so);
2055 ng_btsocket_rfcomm_pcb_kill(pcb, error);
2057 mtx_unlock(&pcb->pcb_mtx);
2063 * We do not have requested DLCI, so it must be an incoming connection
2064 * with default parameters. Try to accept it.
2067 pcb = ng_btsocket_rfcomm_connect_ind(s, RFCOMM_SRVCHANNEL(dlci));
2069 mtx_lock(&pcb->pcb_mtx);
2073 error = ng_btsocket_rfcomm_send_command(s,RFCOMM_FRAME_UA,dlci);
2075 error = ng_btsocket_rfcomm_send_msc(pcb);
2078 pcb->state = NG_BTSOCKET_RFCOMM_DLC_CONNECTED;
2079 soisconnected(pcb->so);
2081 ng_btsocket_rfcomm_pcb_kill(pcb, error);
2083 mtx_unlock(&pcb->pcb_mtx);
2085 /* Nobody is listen()ing on the requested DLCI */
2086 error = ng_btsocket_rfcomm_send_command(s,RFCOMM_FRAME_DM,dlci);
2089 } /* ng_btsocket_rfcomm_receive_sabm */
2092 * Process RFCOMM DISC frame
2096 ng_btsocket_rfcomm_receive_disc(ng_btsocket_rfcomm_session_p s, int dlci)
2098 ng_btsocket_rfcomm_pcb_p pcb = NULL;
2101 mtx_assert(&s->session_mtx, MA_OWNED);
2103 NG_BTSOCKET_RFCOMM_INFO(
2104 "%s: Got DISC, session state=%d, flags=%#x, mtu=%d, dlci=%d\n",
2105 __func__, s->state, s->flags, s->mtu, dlci);
2107 /* DLCI == 0 means close multiplexor channel */
2109 /* XXX FIXME assume that remote side will close the socket */
2110 error = ng_btsocket_rfcomm_send_command(s, RFCOMM_FRAME_UA, 0);
2112 if (s->state == NG_BTSOCKET_RFCOMM_SESSION_DISCONNECTING)
2113 s->state = NG_BTSOCKET_RFCOMM_SESSION_CLOSED; /* XXX */
2115 s->state = NG_BTSOCKET_RFCOMM_SESSION_DISCONNECTING;
2117 s->state = NG_BTSOCKET_RFCOMM_SESSION_CLOSED; /* XXX */
2119 ng_btsocket_rfcomm_session_clean(s);
2121 pcb = ng_btsocket_rfcomm_pcb_by_dlci(s, dlci);
2125 mtx_lock(&pcb->pcb_mtx);
2127 NG_BTSOCKET_RFCOMM_INFO(
2128 "%s: Got DISC for dlci=%d, state=%d, flags=%#x\n",
2129 __func__, dlci, pcb->state, pcb->flags);
2131 error = ng_btsocket_rfcomm_send_command(s,
2132 RFCOMM_FRAME_UA, dlci);
2134 if (pcb->state == NG_BTSOCKET_RFCOMM_DLC_CONNECTED)
2139 ng_btsocket_rfcomm_pcb_kill(pcb, err);
2141 mtx_unlock(&pcb->pcb_mtx);
2143 NG_BTSOCKET_RFCOMM_WARN(
2144 "%s: Got DISC for non-existing dlci=%d\n", __func__, dlci);
2146 error = ng_btsocket_rfcomm_send_command(s,
2147 RFCOMM_FRAME_DM, dlci);
2152 } /* ng_btsocket_rfcomm_receive_disc */
2155 * Process RFCOMM UA frame
2159 ng_btsocket_rfcomm_receive_ua(ng_btsocket_rfcomm_session_p s, int dlci)
2161 ng_btsocket_rfcomm_pcb_p pcb = NULL;
2164 mtx_assert(&s->session_mtx, MA_OWNED);
2166 NG_BTSOCKET_RFCOMM_INFO(
2167 "%s: Got UA, session state=%d, flags=%#x, mtu=%d, dlci=%d\n",
2168 __func__, s->state, s->flags, s->mtu, dlci);
2170 /* dlci == 0 means multiplexor channel */
2173 case NG_BTSOCKET_RFCOMM_SESSION_CONNECTED:
2174 s->state = NG_BTSOCKET_RFCOMM_SESSION_OPEN;
2175 ng_btsocket_rfcomm_connect_cfm(s);
2178 case NG_BTSOCKET_RFCOMM_SESSION_DISCONNECTING:
2179 s->state = NG_BTSOCKET_RFCOMM_SESSION_CLOSED;
2180 ng_btsocket_rfcomm_session_clean(s);
2184 NG_BTSOCKET_RFCOMM_WARN(
2185 "%s: Got UA for session in invalid state=%d(%d), flags=%#x, mtu=%d\n",
2186 __func__, s->state, INITIATOR(s), s->flags,
2195 /* Check if we have this DLCI */
2196 pcb = ng_btsocket_rfcomm_pcb_by_dlci(s, dlci);
2198 mtx_lock(&pcb->pcb_mtx);
2200 NG_BTSOCKET_RFCOMM_INFO(
2201 "%s: Got UA for dlci=%d, state=%d, flags=%#x\n",
2202 __func__, dlci, pcb->state, pcb->flags);
2204 switch (pcb->state) {
2205 case NG_BTSOCKET_RFCOMM_DLC_CONNECTING:
2206 ng_btsocket_rfcomm_untimeout(pcb);
2208 error = ng_btsocket_rfcomm_send_msc(pcb);
2210 pcb->state = NG_BTSOCKET_RFCOMM_DLC_CONNECTED;
2211 soisconnected(pcb->so);
2215 case NG_BTSOCKET_RFCOMM_DLC_DISCONNECTING:
2216 ng_btsocket_rfcomm_pcb_kill(pcb, 0);
2220 NG_BTSOCKET_RFCOMM_WARN(
2221 "%s: Got UA for dlci=%d in invalid state=%d, flags=%#x\n",
2222 __func__, dlci, pcb->state, pcb->flags);
2227 mtx_unlock(&pcb->pcb_mtx);
2229 NG_BTSOCKET_RFCOMM_WARN(
2230 "%s: Got UA for non-existing dlci=%d\n", __func__, dlci);
2232 error = ng_btsocket_rfcomm_send_command(s,RFCOMM_FRAME_DM,dlci);
2236 } /* ng_btsocket_rfcomm_receive_ua */
2239 * Process RFCOMM DM frame
2243 ng_btsocket_rfcomm_receive_dm(ng_btsocket_rfcomm_session_p s, int dlci)
2245 ng_btsocket_rfcomm_pcb_p pcb = NULL;
2248 mtx_assert(&s->session_mtx, MA_OWNED);
2250 NG_BTSOCKET_RFCOMM_INFO(
2251 "%s: Got DM, session state=%d, flags=%#x, mtu=%d, dlci=%d\n",
2252 __func__, s->state, s->flags, s->mtu, dlci);
2254 /* DLCI == 0 means multiplexor channel */
2256 /* Disconnect all dlc's on the session */
2257 s->state = NG_BTSOCKET_RFCOMM_SESSION_CLOSED;
2258 ng_btsocket_rfcomm_session_clean(s);
2260 pcb = ng_btsocket_rfcomm_pcb_by_dlci(s, dlci);
2262 mtx_lock(&pcb->pcb_mtx);
2264 NG_BTSOCKET_RFCOMM_INFO(
2265 "%s: Got DM for dlci=%d, state=%d, flags=%#x\n",
2266 __func__, dlci, pcb->state, pcb->flags);
2268 if (pcb->state == NG_BTSOCKET_RFCOMM_DLC_CONNECTED)
2271 error = ECONNREFUSED;
2273 ng_btsocket_rfcomm_pcb_kill(pcb, error);
2275 mtx_unlock(&pcb->pcb_mtx);
2277 NG_BTSOCKET_RFCOMM_WARN(
2278 "%s: Got DM for non-existing dlci=%d\n", __func__, dlci);
2282 } /* ng_btsocket_rfcomm_receive_dm */
2285 * Process RFCOMM UIH frame (data)
2289 ng_btsocket_rfcomm_receive_uih(ng_btsocket_rfcomm_session_p s, int dlci,
2290 int pf, struct mbuf *m0)
2292 ng_btsocket_rfcomm_pcb_p pcb = NULL;
2295 mtx_assert(&s->session_mtx, MA_OWNED);
2297 NG_BTSOCKET_RFCOMM_INFO(
2298 "%s: Got UIH, session state=%d, flags=%#x, mtu=%d, dlci=%d, pf=%d, len=%d\n",
2299 __func__, s->state, s->flags, s->mtu, dlci, pf,
2302 /* XXX should we do it here? Check for session flow control */
2303 if (s->flags & NG_BTSOCKET_RFCOMM_SESSION_LFC) {
2304 NG_BTSOCKET_RFCOMM_WARN(
2305 "%s: Got UIH with session flow control asserted, state=%d, flags=%#x\n",
2306 __func__, s->state, s->flags);
2310 /* Check if we have this dlci */
2311 pcb = ng_btsocket_rfcomm_pcb_by_dlci(s, dlci);
2313 NG_BTSOCKET_RFCOMM_WARN(
2314 "%s: Got UIH for non-existing dlci=%d\n", __func__, dlci);
2315 error = ng_btsocket_rfcomm_send_command(s,RFCOMM_FRAME_DM,dlci);
2319 mtx_lock(&pcb->pcb_mtx);
2321 /* Check dlci state */
2322 if (pcb->state != NG_BTSOCKET_RFCOMM_DLC_CONNECTED) {
2323 NG_BTSOCKET_RFCOMM_WARN(
2324 "%s: Got UIH for dlci=%d in invalid state=%d, flags=%#x\n",
2325 __func__, dlci, pcb->state, pcb->flags);
2330 /* Check dlci flow control */
2331 if (((pcb->flags & NG_BTSOCKET_RFCOMM_DLC_CFC) && pcb->rx_cred <= 0) ||
2332 (pcb->lmodem & RFCOMM_MODEM_FC)) {
2333 NG_BTSOCKET_RFCOMM_ERR(
2334 "%s: Got UIH for dlci=%d with asserted flow control, state=%d, " \
2335 "flags=%#x, rx_cred=%d, lmodem=%#x\n",
2336 __func__, dlci, pcb->state, pcb->flags,
2337 pcb->rx_cred, pcb->lmodem);
2341 /* Did we get any credits? */
2342 if ((pcb->flags & NG_BTSOCKET_RFCOMM_DLC_CFC) && pf) {
2343 NG_BTSOCKET_RFCOMM_INFO(
2344 "%s: Got %d more credits for dlci=%d, state=%d, flags=%#x, " \
2345 "rx_cred=%d, tx_cred=%d\n",
2346 __func__, *mtod(m0, u_int8_t *), dlci, pcb->state,
2347 pcb->flags, pcb->rx_cred, pcb->tx_cred);
2349 pcb->tx_cred += *mtod(m0, u_int8_t *);
2352 /* Send more from the DLC. XXX check for errors? */
2353 ng_btsocket_rfcomm_pcb_send(pcb, ALOT);
2356 /* OK the of the rest of the mbuf is the data */
2357 if (m0->m_pkthdr.len > 0) {
2358 /* If we are using credit flow control decrease rx_cred here */
2359 if (pcb->flags & NG_BTSOCKET_RFCOMM_DLC_CFC) {
2360 /* Give remote peer more credits (if needed) */
2361 if (-- pcb->rx_cred <= RFCOMM_MAX_CREDITS / 2)
2362 ng_btsocket_rfcomm_send_credits(pcb);
2364 NG_BTSOCKET_RFCOMM_INFO(
2365 "%s: Remote side still has credits, dlci=%d, state=%d, flags=%#x, " \
2366 "rx_cred=%d, tx_cred=%d\n", __func__, dlci, pcb->state, pcb->flags,
2367 pcb->rx_cred, pcb->tx_cred);
2370 /* Check packet against mtu on dlci */
2371 if (m0->m_pkthdr.len > pcb->mtu) {
2372 NG_BTSOCKET_RFCOMM_ERR(
2373 "%s: Got oversized UIH for dlci=%d, state=%d, flags=%#x, mtu=%d, len=%d\n",
2374 __func__, dlci, pcb->state, pcb->flags,
2375 pcb->mtu, m0->m_pkthdr.len);
2378 } else if (m0->m_pkthdr.len > sbspace(&pcb->so->so_rcv)) {
2381 * This is really bad. Receive queue on socket does
2382 * not have enough space for the packet. We do not
2383 * have any other choice but drop the packet.
2386 NG_BTSOCKET_RFCOMM_ERR(
2387 "%s: Not enough space in socket receive queue. Dropping UIH for dlci=%d, " \
2388 "state=%d, flags=%#x, len=%d, space=%ld\n",
2389 __func__, dlci, pcb->state, pcb->flags,
2390 m0->m_pkthdr.len, sbspace(&pcb->so->so_rcv));
2394 /* Append packet to the socket receive queue */
2395 sbappend(&pcb->so->so_rcv, m0);
2402 mtx_unlock(&pcb->pcb_mtx);
2404 NG_FREE_M(m0); /* checks for != NULL */
2407 } /* ng_btsocket_rfcomm_receive_uih */
2410 * Process RFCOMM MCC command (Multiplexor)
2412 * From TS 07.10 spec
2414 * "5.4.3.1 Information Data
2416 * ...The frames (UIH) sent by the initiating station have the C/R bit set
2417 * to 1 and those sent by the responding station have the C/R bit set to 0..."
2419 * "5.4.6.2 Operating procedures
2421 * Messages always exist in pairs; a command message and a corresponding
2422 * response message. If the C/R bit is set to 1 the message is a command,
2423 * if it is set to 0 the message is a response...
2427 * NOTE: Notice that when UIH frames are used to convey information on DLCI 0
2428 * there are at least two different fields that contain a C/R bit, and the
2429 * bits are set of different form. The C/R bit in the Type field shall be set
2430 * as it is stated above, while the C/R bit in the Address field (see subclause
2431 * 5.2.1.2) shall be set as it is described in subclause 5.4.3.1."
2435 ng_btsocket_rfcomm_receive_mcc(ng_btsocket_rfcomm_session_p s, struct mbuf *m0)
2437 struct rfcomm_mcc_hdr *hdr = NULL;
2438 u_int8_t cr, type, length;
2440 mtx_assert(&s->session_mtx, MA_OWNED);
2443 * We can access data directly in the first mbuf, because we have
2444 * m_pullup()'ed mbuf chain in ng_btsocket_rfcomm_receive_frame().
2445 * All MCC commands should fit into single mbuf (except probably TEST).
2448 hdr = mtod(m0, struct rfcomm_mcc_hdr *);
2449 cr = RFCOMM_CR(hdr->type);
2450 type = RFCOMM_MCC_TYPE(hdr->type);
2451 length = RFCOMM_MCC_LENGTH(hdr->length);
2453 /* Check MCC frame length */
2454 if (sizeof(*hdr) + length != m0->m_pkthdr.len) {
2455 NG_BTSOCKET_RFCOMM_ERR(
2456 "%s: Invalid MCC frame length=%d, len=%d\n",
2457 __func__, length, m0->m_pkthdr.len);
2464 case RFCOMM_MCC_TEST:
2465 return (ng_btsocket_rfcomm_receive_test(s, m0));
2468 case RFCOMM_MCC_FCON:
2469 case RFCOMM_MCC_FCOFF:
2470 return (ng_btsocket_rfcomm_receive_fc(s, m0));
2473 case RFCOMM_MCC_MSC:
2474 return (ng_btsocket_rfcomm_receive_msc(s, m0));
2477 case RFCOMM_MCC_RPN:
2478 return (ng_btsocket_rfcomm_receive_rpn(s, m0));
2481 case RFCOMM_MCC_RLS:
2482 return (ng_btsocket_rfcomm_receive_rls(s, m0));
2486 return (ng_btsocket_rfcomm_receive_pn(s, m0));
2489 case RFCOMM_MCC_NSC:
2490 NG_BTSOCKET_RFCOMM_ERR(
2491 "%s: Got MCC NSC, type=%#x, cr=%d, length=%d, session state=%d, flags=%#x, " \
2492 "mtu=%d, len=%d\n", __func__, RFCOMM_MCC_TYPE(*((u_int8_t *)(hdr + 1))), cr,
2493 length, s->state, s->flags, s->mtu, m0->m_pkthdr.len);
2498 NG_BTSOCKET_RFCOMM_ERR(
2499 "%s: Got unknown MCC, type=%#x, cr=%d, length=%d, session state=%d, " \
2500 "flags=%#x, mtu=%d, len=%d\n",
2501 __func__, type, cr, length, s->state, s->flags,
2502 s->mtu, m0->m_pkthdr.len);
2504 /* Reuse mbuf to send NSC */
2505 hdr = mtod(m0, struct rfcomm_mcc_hdr *);
2506 m0->m_pkthdr.len = m0->m_len = sizeof(*hdr);
2508 /* Create MCC NSC header */
2509 hdr->type = RFCOMM_MKMCC_TYPE(0, RFCOMM_MCC_NSC);
2510 hdr->length = RFCOMM_MKLEN8(1);
2512 /* Put back MCC command type we did not like */
2513 m0->m_data[m0->m_len] = RFCOMM_MKMCC_TYPE(cr, type);
2514 m0->m_pkthdr.len ++;
2517 /* Send UIH frame */
2518 return (ng_btsocket_rfcomm_send_uih(s,
2519 RFCOMM_MKADDRESS(INITIATOR(s), 0), 0, 0, m0));
2524 } /* ng_btsocket_rfcomm_receive_mcc */
2527 * Receive RFCOMM TEST MCC command
2531 ng_btsocket_rfcomm_receive_test(ng_btsocket_rfcomm_session_p s, struct mbuf *m0)
2533 struct rfcomm_mcc_hdr *hdr = mtod(m0, struct rfcomm_mcc_hdr *);
2536 mtx_assert(&s->session_mtx, MA_OWNED);
2538 NG_BTSOCKET_RFCOMM_INFO(
2539 "%s: Got MCC TEST, cr=%d, length=%d, session state=%d, flags=%#x, mtu=%d, " \
2540 "len=%d\n", __func__, RFCOMM_CR(hdr->type), RFCOMM_MCC_LENGTH(hdr->length),
2541 s->state, s->flags, s->mtu, m0->m_pkthdr.len);
2543 if (RFCOMM_CR(hdr->type)) {
2544 hdr->type = RFCOMM_MKMCC_TYPE(0, RFCOMM_MCC_TEST);
2545 error = ng_btsocket_rfcomm_send_uih(s,
2546 RFCOMM_MKADDRESS(INITIATOR(s), 0), 0, 0, m0);
2548 NG_FREE_M(m0); /* XXX ignore response */
2551 } /* ng_btsocket_rfcomm_receive_test */
2554 * Receive RFCOMM FCON/FCOFF MCC command
2558 ng_btsocket_rfcomm_receive_fc(ng_btsocket_rfcomm_session_p s, struct mbuf *m0)
2560 struct rfcomm_mcc_hdr *hdr = mtod(m0, struct rfcomm_mcc_hdr *);
2561 u_int8_t type = RFCOMM_MCC_TYPE(hdr->type);
2564 mtx_assert(&s->session_mtx, MA_OWNED);
2567 * Turn ON/OFF aggregate flow on the entire session. When remote peer
2568 * asserted flow control no transmission shall occur except on dlci 0
2569 * (control channel).
2572 NG_BTSOCKET_RFCOMM_INFO(
2573 "%s: Got MCC FC%s, cr=%d, length=%d, session state=%d, flags=%#x, mtu=%d, " \
2574 "len=%d\n", __func__, (type == RFCOMM_MCC_FCON)? "ON" : "OFF",
2575 RFCOMM_CR(hdr->type), RFCOMM_MCC_LENGTH(hdr->length),
2576 s->state, s->flags, s->mtu, m0->m_pkthdr.len);
2578 if (RFCOMM_CR(hdr->type)) {
2579 if (type == RFCOMM_MCC_FCON)
2580 s->flags &= ~NG_BTSOCKET_RFCOMM_SESSION_RFC;
2582 s->flags |= NG_BTSOCKET_RFCOMM_SESSION_RFC;
2584 hdr->type = RFCOMM_MKMCC_TYPE(0, type);
2585 error = ng_btsocket_rfcomm_send_uih(s,
2586 RFCOMM_MKADDRESS(INITIATOR(s), 0), 0, 0, m0);
2588 NG_FREE_M(m0); /* XXX ignore response */
2591 } /* ng_btsocket_rfcomm_receive_fc */
2594 * Receive RFCOMM MSC MCC command
2598 ng_btsocket_rfcomm_receive_msc(ng_btsocket_rfcomm_session_p s, struct mbuf *m0)
2600 struct rfcomm_mcc_hdr *hdr = mtod(m0, struct rfcomm_mcc_hdr*);
2601 struct rfcomm_mcc_msc *msc = (struct rfcomm_mcc_msc *)(hdr+1);
2602 ng_btsocket_rfcomm_pcb_t *pcb = NULL;
2605 mtx_assert(&s->session_mtx, MA_OWNED);
2607 NG_BTSOCKET_RFCOMM_INFO(
2608 "%s: Got MCC MSC, dlci=%d, cr=%d, length=%d, session state=%d, flags=%#x, " \
2610 __func__, RFCOMM_DLCI(msc->address), RFCOMM_CR(hdr->type),
2611 RFCOMM_MCC_LENGTH(hdr->length), s->state, s->flags,
2612 s->mtu, m0->m_pkthdr.len);
2614 if (RFCOMM_CR(hdr->type)) {
2615 pcb = ng_btsocket_rfcomm_pcb_by_dlci(s, RFCOMM_DLCI(msc->address));
2617 NG_BTSOCKET_RFCOMM_WARN(
2618 "%s: Got MSC command for non-existing dlci=%d\n",
2619 __func__, RFCOMM_DLCI(msc->address));
2625 mtx_lock(&pcb->pcb_mtx);
2627 if (pcb->state != NG_BTSOCKET_RFCOMM_DLC_CONNECTING &&
2628 pcb->state != NG_BTSOCKET_RFCOMM_DLC_CONNECTED) {
2629 NG_BTSOCKET_RFCOMM_WARN(
2630 "%s: Got MSC on dlci=%d in invalid state=%d\n",
2631 __func__, RFCOMM_DLCI(msc->address),
2634 mtx_unlock(&pcb->pcb_mtx);
2640 pcb->rmodem = msc->modem; /* Update remote port signals */
2642 hdr->type = RFCOMM_MKMCC_TYPE(0, RFCOMM_MCC_MSC);
2643 error = ng_btsocket_rfcomm_send_uih(s,
2644 RFCOMM_MKADDRESS(INITIATOR(s), 0), 0, 0, m0);
2647 /* Send more data from DLC. XXX check for errors? */
2648 if (!(pcb->rmodem & RFCOMM_MODEM_FC) &&
2649 !(pcb->flags & NG_BTSOCKET_RFCOMM_DLC_CFC))
2650 ng_btsocket_rfcomm_pcb_send(pcb, ALOT);
2653 mtx_unlock(&pcb->pcb_mtx);
2655 NG_FREE_M(m0); /* XXX ignore response */
2658 } /* ng_btsocket_rfcomm_receive_msc */
2661 * Receive RFCOMM RPN MCC command
2662 * XXX FIXME do we need htole16/le16toh for RPN param_mask?
2666 ng_btsocket_rfcomm_receive_rpn(ng_btsocket_rfcomm_session_p s, struct mbuf *m0)
2668 struct rfcomm_mcc_hdr *hdr = mtod(m0, struct rfcomm_mcc_hdr *);
2669 struct rfcomm_mcc_rpn *rpn = (struct rfcomm_mcc_rpn *)(hdr + 1);
2671 u_int16_t param_mask;
2672 u_int8_t bit_rate, data_bits, stop_bits, parity,
2673 flow_control, xon_char, xoff_char;
2675 mtx_assert(&s->session_mtx, MA_OWNED);
2677 NG_BTSOCKET_RFCOMM_INFO(
2678 "%s: Got MCC RPN, dlci=%d, cr=%d, length=%d, session state=%d, flags=%#x, " \
2680 __func__, RFCOMM_DLCI(rpn->dlci), RFCOMM_CR(hdr->type),
2681 RFCOMM_MCC_LENGTH(hdr->length), s->state, s->flags,
2682 s->mtu, m0->m_pkthdr.len);
2684 if (RFCOMM_CR(hdr->type)) {
2685 param_mask = RFCOMM_RPN_PM_ALL;
2687 if (RFCOMM_MCC_LENGTH(hdr->length) == 1) {
2688 /* Request - return default setting */
2689 bit_rate = RFCOMM_RPN_BR_115200;
2690 data_bits = RFCOMM_RPN_DATA_8;
2691 stop_bits = RFCOMM_RPN_STOP_1;
2692 parity = RFCOMM_RPN_PARITY_NONE;
2693 flow_control = RFCOMM_RPN_FLOW_NONE;
2694 xon_char = RFCOMM_RPN_XON_CHAR;
2695 xoff_char = RFCOMM_RPN_XOFF_CHAR;
2698 * Ignore/accept bit_rate, 8 bits, 1 stop bit, no
2699 * parity, no flow control lines, default XON/XOFF
2703 bit_rate = rpn->bit_rate;
2704 rpn->param_mask = le16toh(rpn->param_mask); /* XXX */
2706 data_bits = RFCOMM_RPN_DATA_BITS(rpn->line_settings);
2707 if (rpn->param_mask & RFCOMM_RPN_PM_DATA &&
2708 data_bits != RFCOMM_RPN_DATA_8) {
2709 data_bits = RFCOMM_RPN_DATA_8;
2710 param_mask ^= RFCOMM_RPN_PM_DATA;
2713 stop_bits = RFCOMM_RPN_STOP_BITS(rpn->line_settings);
2714 if (rpn->param_mask & RFCOMM_RPN_PM_STOP &&
2715 stop_bits != RFCOMM_RPN_STOP_1) {
2716 stop_bits = RFCOMM_RPN_STOP_1;
2717 param_mask ^= RFCOMM_RPN_PM_STOP;
2720 parity = RFCOMM_RPN_PARITY(rpn->line_settings);
2721 if (rpn->param_mask & RFCOMM_RPN_PM_PARITY &&
2722 parity != RFCOMM_RPN_PARITY_NONE) {
2723 parity = RFCOMM_RPN_PARITY_NONE;
2724 param_mask ^= RFCOMM_RPN_PM_PARITY;
2727 flow_control = rpn->flow_control;
2728 if (rpn->param_mask & RFCOMM_RPN_PM_FLOW &&
2729 flow_control != RFCOMM_RPN_FLOW_NONE) {
2730 flow_control = RFCOMM_RPN_FLOW_NONE;
2731 param_mask ^= RFCOMM_RPN_PM_FLOW;
2734 xon_char = rpn->xon_char;
2735 if (rpn->param_mask & RFCOMM_RPN_PM_XON &&
2736 xon_char != RFCOMM_RPN_XON_CHAR) {
2737 xon_char = RFCOMM_RPN_XON_CHAR;
2738 param_mask ^= RFCOMM_RPN_PM_XON;
2741 xoff_char = rpn->xoff_char;
2742 if (rpn->param_mask & RFCOMM_RPN_PM_XOFF &&
2743 xoff_char != RFCOMM_RPN_XOFF_CHAR) {
2744 xoff_char = RFCOMM_RPN_XOFF_CHAR;
2745 param_mask ^= RFCOMM_RPN_PM_XOFF;
2749 rpn->bit_rate = bit_rate;
2750 rpn->line_settings = RFCOMM_MKRPN_LINE_SETTINGS(data_bits,
2752 rpn->flow_control = flow_control;
2753 rpn->xon_char = xon_char;
2754 rpn->xoff_char = xoff_char;
2755 rpn->param_mask = htole16(param_mask); /* XXX */
2757 m0->m_pkthdr.len = m0->m_len = sizeof(*hdr) + sizeof(*rpn);
2759 hdr->type = RFCOMM_MKMCC_TYPE(0, RFCOMM_MCC_RPN);
2760 error = ng_btsocket_rfcomm_send_uih(s,
2761 RFCOMM_MKADDRESS(INITIATOR(s), 0), 0, 0, m0);
2763 NG_FREE_M(m0); /* XXX ignore response */
2766 } /* ng_btsocket_rfcomm_receive_rpn */
2769 * Receive RFCOMM RLS MCC command
2773 ng_btsocket_rfcomm_receive_rls(ng_btsocket_rfcomm_session_p s, struct mbuf *m0)
2775 struct rfcomm_mcc_hdr *hdr = mtod(m0, struct rfcomm_mcc_hdr *);
2776 struct rfcomm_mcc_rls *rls = (struct rfcomm_mcc_rls *)(hdr + 1);
2779 mtx_assert(&s->session_mtx, MA_OWNED);
2782 * XXX FIXME Do we have to do anything else here? Remote peer tries to
2783 * tell us something about DLCI. Just report what we have received and
2784 * return back received values as required by TS 07.10 spec.
2787 NG_BTSOCKET_RFCOMM_INFO(
2788 "%s: Got MCC RLS, dlci=%d, status=%#x, cr=%d, length=%d, session state=%d, " \
2789 "flags=%#x, mtu=%d, len=%d\n",
2790 __func__, RFCOMM_DLCI(rls->address), rls->status,
2791 RFCOMM_CR(hdr->type), RFCOMM_MCC_LENGTH(hdr->length),
2792 s->state, s->flags, s->mtu, m0->m_pkthdr.len);
2794 if (RFCOMM_CR(hdr->type)) {
2795 if (rls->status & 0x1)
2796 NG_BTSOCKET_RFCOMM_ERR(
2797 "%s: Got RLS dlci=%d, error=%#x\n", __func__, RFCOMM_DLCI(rls->address),
2800 hdr->type = RFCOMM_MKMCC_TYPE(0, RFCOMM_MCC_RLS);
2801 error = ng_btsocket_rfcomm_send_uih(s,
2802 RFCOMM_MKADDRESS(INITIATOR(s), 0), 0, 0, m0);
2804 NG_FREE_M(m0); /* XXX ignore responses */
2807 } /* ng_btsocket_rfcomm_receive_rls */
2810 * Receive RFCOMM PN MCC command
2814 ng_btsocket_rfcomm_receive_pn(ng_btsocket_rfcomm_session_p s, struct mbuf *m0)
2816 struct rfcomm_mcc_hdr *hdr = mtod(m0, struct rfcomm_mcc_hdr*);
2817 struct rfcomm_mcc_pn *pn = (struct rfcomm_mcc_pn *)(hdr+1);
2818 ng_btsocket_rfcomm_pcb_t *pcb = NULL;
2821 mtx_assert(&s->session_mtx, MA_OWNED);
2823 NG_BTSOCKET_RFCOMM_INFO(
2824 "%s: Got MCC PN, dlci=%d, cr=%d, length=%d, flow_control=%#x, priority=%d, " \
2825 "ack_timer=%d, mtu=%d, max_retrans=%d, credits=%d, session state=%d, " \
2826 "flags=%#x, session mtu=%d, len=%d\n",
2827 __func__, pn->dlci, RFCOMM_CR(hdr->type),
2828 RFCOMM_MCC_LENGTH(hdr->length), pn->flow_control, pn->priority,
2829 pn->ack_timer, le16toh(pn->mtu), pn->max_retrans, pn->credits,
2830 s->state, s->flags, s->mtu, m0->m_pkthdr.len);
2832 if (pn->dlci == 0) {
2833 NG_BTSOCKET_RFCOMM_ERR("%s: Zero dlci in MCC PN\n", __func__);
2839 /* Check if we have this dlci */
2840 pcb = ng_btsocket_rfcomm_pcb_by_dlci(s, pn->dlci);
2842 mtx_lock(&pcb->pcb_mtx);
2844 if (RFCOMM_CR(hdr->type)) {
2846 ng_btsocket_rfcomm_set_pn(pcb, 1, pn->flow_control,
2847 pn->credits, pn->mtu);
2849 if (pcb->flags & NG_BTSOCKET_RFCOMM_DLC_CFC) {
2850 pn->flow_control = 0xe0;
2851 pn->credits = RFCOMM_DEFAULT_CREDITS;
2853 pn->flow_control = 0;
2857 hdr->type = RFCOMM_MKMCC_TYPE(0, RFCOMM_MCC_PN);
2858 error = ng_btsocket_rfcomm_send_uih(s,
2859 RFCOMM_MKADDRESS(INITIATOR(s), 0),
2862 /* PN Response - proceed with SABM. Timeout still set */
2863 if (pcb->state == NG_BTSOCKET_RFCOMM_DLC_CONFIGURING) {
2864 ng_btsocket_rfcomm_set_pn(pcb, 0,
2865 pn->flow_control, pn->credits, pn->mtu);
2867 pcb->state = NG_BTSOCKET_RFCOMM_DLC_CONNECTING;
2868 error = ng_btsocket_rfcomm_send_command(s,
2869 RFCOMM_FRAME_SABM, pn->dlci);
2871 NG_BTSOCKET_RFCOMM_WARN(
2872 "%s: Got PN response for dlci=%d in invalid state=%d\n",
2873 __func__, pn->dlci, pcb->state);
2878 mtx_unlock(&pcb->pcb_mtx);
2879 } else if (RFCOMM_CR(hdr->type)) {
2880 /* PN request to non-existing dlci - incomming connection */
2881 pcb = ng_btsocket_rfcomm_connect_ind(s,
2882 RFCOMM_SRVCHANNEL(pn->dlci));
2884 mtx_lock(&pcb->pcb_mtx);
2886 pcb->dlci = pn->dlci;
2888 ng_btsocket_rfcomm_set_pn(pcb, 1, pn->flow_control,
2889 pn->credits, pn->mtu);
2891 if (pcb->flags & NG_BTSOCKET_RFCOMM_DLC_CFC) {
2892 pn->flow_control = 0xe0;
2893 pn->credits = RFCOMM_DEFAULT_CREDITS;
2895 pn->flow_control = 0;
2899 hdr->type = RFCOMM_MKMCC_TYPE(0, RFCOMM_MCC_PN);
2900 error = ng_btsocket_rfcomm_send_uih(s,
2901 RFCOMM_MKADDRESS(INITIATOR(s), 0),
2905 ng_btsocket_rfcomm_timeout(pcb);
2906 pcb->state = NG_BTSOCKET_RFCOMM_DLC_CONNECTING;
2907 soisconnecting(pcb->so);
2909 ng_btsocket_rfcomm_pcb_kill(pcb, error);
2911 mtx_unlock(&pcb->pcb_mtx);
2913 /* Nobody is listen()ing on this channel */
2914 error = ng_btsocket_rfcomm_send_command(s,
2915 RFCOMM_FRAME_DM, pn->dlci);
2919 NG_FREE_M(m0); /* XXX ignore response to non-existing dlci */
2922 } /* ng_btsocket_rfcomm_receive_pn */
2925 * Set PN parameters for dlci. Caller must hold pcb->pcb_mtx.
2927 * From Bluetooth spec.
2929 * "... The CL1 - CL4 field is completely redefined. (In TS07.10 this defines
2930 * the convergence layer to use, which is not applicable to RFCOMM. In RFCOMM,
2931 * in Bluetooth versions up to 1.0B, this field was forced to 0).
2933 * In the PN request sent prior to a DLC establishment, this field must contain
2934 * the value 15 (0xF), indicating support of credit based flow control in the
2935 * sender. See Table 5.3 below. If the PN response contains any other value
2936 * than 14 (0xE) in this field, it is inferred that the peer RFCOMM entity is
2937 * not supporting the credit based flow control feature. (This is only possible
2938 * if the peer RFCOMM implementation is only conforming to Bluetooth version
2939 * 1.0B.) If a PN request is sent on an already open DLC, then this field must
2940 * contain the value zero; it is not possible to set initial credits more
2941 * than once per DLC activation. A responding implementation must set this
2942 * field in the PN response to 14 (0xE), if (and only if) the value in the PN
2943 * request was 15..."
2947 ng_btsocket_rfcomm_set_pn(ng_btsocket_rfcomm_pcb_p pcb, u_int8_t cr,
2948 u_int8_t flow_control, u_int8_t credits, u_int16_t mtu)
2950 mtx_assert(&pcb->pcb_mtx, MA_OWNED);
2952 pcb->mtu = le16toh(mtu);
2955 if (flow_control == 0xf0) {
2956 pcb->flags |= NG_BTSOCKET_RFCOMM_DLC_CFC;
2957 pcb->tx_cred = credits;
2959 pcb->flags &= ~NG_BTSOCKET_RFCOMM_DLC_CFC;
2963 if (flow_control == 0xe0) {
2964 pcb->flags |= NG_BTSOCKET_RFCOMM_DLC_CFC;
2965 pcb->tx_cred = credits;
2967 pcb->flags &= ~NG_BTSOCKET_RFCOMM_DLC_CFC;
2972 NG_BTSOCKET_RFCOMM_INFO(
2973 "%s: cr=%d, dlci=%d, state=%d, flags=%#x, mtu=%d, rx_cred=%d, tx_cred=%d\n",
2974 __func__, cr, pcb->dlci, pcb->state, pcb->flags, pcb->mtu,
2975 pcb->rx_cred, pcb->tx_cred);
2976 } /* ng_btsocket_rfcomm_set_pn */
2979 * Send RFCOMM SABM/DISC/UA/DM frames. Caller must hold s->session_mtx
2983 ng_btsocket_rfcomm_send_command(ng_btsocket_rfcomm_session_p s,
2984 u_int8_t type, u_int8_t dlci)
2986 struct rfcomm_cmd_hdr *hdr = NULL;
2987 struct mbuf *m = NULL;
2990 mtx_assert(&s->session_mtx, MA_OWNED);
2992 NG_BTSOCKET_RFCOMM_INFO(
2993 "%s: Sending command type %#x, session state=%d, flags=%#x, mtu=%d, dlci=%d\n",
2994 __func__, type, s->state, s->flags, s->mtu, dlci);
2997 case RFCOMM_FRAME_SABM:
2998 case RFCOMM_FRAME_DISC:
3002 case RFCOMM_FRAME_UA:
3003 case RFCOMM_FRAME_DM:
3008 panic("%s: Invalid frame type=%#x\n", __func__, type);
3013 MGETHDR(m, M_NOWAIT, MT_DATA);
3017 m->m_pkthdr.len = m->m_len = sizeof(*hdr);
3019 hdr = mtod(m, struct rfcomm_cmd_hdr *);
3020 hdr->address = RFCOMM_MKADDRESS(cr, dlci);
3021 hdr->control = RFCOMM_MKCONTROL(type, 1);
3022 hdr->length = RFCOMM_MKLEN8(0);
3023 hdr->fcs = ng_btsocket_rfcomm_fcs3((u_int8_t *) hdr);
3025 NG_BT_MBUFQ_ENQUEUE(&s->outq, m);
3028 } /* ng_btsocket_rfcomm_send_command */
3031 * Send RFCOMM UIH frame. Caller must hold s->session_mtx
3035 ng_btsocket_rfcomm_send_uih(ng_btsocket_rfcomm_session_p s, u_int8_t address,
3036 u_int8_t pf, u_int8_t credits, struct mbuf *data)
3038 struct rfcomm_frame_hdr *hdr = NULL;
3039 struct mbuf *m = NULL, *mcrc = NULL;
3042 mtx_assert(&s->session_mtx, MA_OWNED);
3044 MGETHDR(m, M_NOWAIT, MT_DATA);
3049 m->m_pkthdr.len = m->m_len = sizeof(*hdr);
3051 MGET(mcrc, M_NOWAIT, MT_DATA);
3058 /* Fill UIH frame header */
3059 hdr = mtod(m, struct rfcomm_frame_hdr *);
3060 hdr->address = address;
3061 hdr->control = RFCOMM_MKCONTROL(RFCOMM_FRAME_UIH, pf);
3064 mcrc->m_data[0] = ng_btsocket_rfcomm_fcs2((u_int8_t *) hdr);
3066 /* Put length back */
3067 length = (data != NULL)? data->m_pkthdr.len : 0;
3069 u_int16_t l = htole16(RFCOMM_MKLEN16(length));
3071 bcopy(&l, &hdr->length, sizeof(l));
3075 hdr->length = RFCOMM_MKLEN8(length);
3078 m->m_data[m->m_len] = credits;
3086 m->m_pkthdr.len += length;
3093 NG_BTSOCKET_RFCOMM_INFO(
3094 "%s: Sending UIH state=%d, flags=%#x, address=%d, length=%d, pf=%d, " \
3095 "credits=%d, len=%d\n",
3096 __func__, s->state, s->flags, address, length, pf, credits,
3099 NG_BT_MBUFQ_ENQUEUE(&s->outq, m);
3102 } /* ng_btsocket_rfcomm_send_uih */
3105 * Send MSC request. Caller must hold pcb->pcb_mtx and pcb->session->session_mtx
3109 ng_btsocket_rfcomm_send_msc(ng_btsocket_rfcomm_pcb_p pcb)
3111 struct mbuf *m = NULL;
3112 struct rfcomm_mcc_hdr *hdr = NULL;
3113 struct rfcomm_mcc_msc *msc = NULL;
3115 mtx_assert(&pcb->session->session_mtx, MA_OWNED);
3116 mtx_assert(&pcb->pcb_mtx, MA_OWNED);
3118 MGETHDR(m, M_NOWAIT, MT_DATA);
3122 m->m_pkthdr.len = m->m_len = sizeof(*hdr) + sizeof(*msc);
3124 hdr = mtod(m, struct rfcomm_mcc_hdr *);
3125 msc = (struct rfcomm_mcc_msc *)(hdr + 1);
3127 hdr->type = RFCOMM_MKMCC_TYPE(1, RFCOMM_MCC_MSC);
3128 hdr->length = RFCOMM_MKLEN8(sizeof(*msc));
3130 msc->address = RFCOMM_MKADDRESS(1, pcb->dlci);
3131 msc->modem = pcb->lmodem;
3133 NG_BTSOCKET_RFCOMM_INFO(
3134 "%s: Sending MSC dlci=%d, state=%d, flags=%#x, address=%d, modem=%#x\n",
3135 __func__, pcb->dlci, pcb->state, pcb->flags, msc->address,
3138 return (ng_btsocket_rfcomm_send_uih(pcb->session,
3139 RFCOMM_MKADDRESS(INITIATOR(pcb->session), 0), 0, 0, m));
3140 } /* ng_btsocket_rfcomm_send_msc */
3143 * Send PN request. Caller must hold pcb->pcb_mtx and pcb->session->session_mtx
3147 ng_btsocket_rfcomm_send_pn(ng_btsocket_rfcomm_pcb_p pcb)
3149 struct mbuf *m = NULL;
3150 struct rfcomm_mcc_hdr *hdr = NULL;
3151 struct rfcomm_mcc_pn *pn = NULL;
3153 mtx_assert(&pcb->session->session_mtx, MA_OWNED);
3154 mtx_assert(&pcb->pcb_mtx, MA_OWNED);
3156 MGETHDR(m, M_NOWAIT, MT_DATA);
3160 m->m_pkthdr.len = m->m_len = sizeof(*hdr) + sizeof(*pn);
3162 hdr = mtod(m, struct rfcomm_mcc_hdr *);
3163 pn = (struct rfcomm_mcc_pn *)(hdr + 1);
3165 hdr->type = RFCOMM_MKMCC_TYPE(1, RFCOMM_MCC_PN);
3166 hdr->length = RFCOMM_MKLEN8(sizeof(*pn));
3168 pn->dlci = pcb->dlci;
3171 * Set default DLCI priority as described in GSM 07.10
3172 * (ETSI TS 101 369) clause 5.6 page 42
3175 pn->priority = (pcb->dlci < 56)? (((pcb->dlci >> 3) << 3) + 7) : 61;
3177 pn->mtu = htole16(pcb->mtu);
3178 pn->max_retrans = 0;
3180 if (pcb->flags & NG_BTSOCKET_RFCOMM_DLC_CFC) {
3181 pn->flow_control = 0xf0;
3182 pn->credits = pcb->rx_cred;
3184 pn->flow_control = 0;
3188 NG_BTSOCKET_RFCOMM_INFO(
3189 "%s: Sending PN dlci=%d, state=%d, flags=%#x, mtu=%d, flow_control=%#x, " \
3190 "credits=%d\n", __func__, pcb->dlci, pcb->state, pcb->flags, pcb->mtu,
3191 pn->flow_control, pn->credits);
3193 return (ng_btsocket_rfcomm_send_uih(pcb->session,
3194 RFCOMM_MKADDRESS(INITIATOR(pcb->session), 0), 0, 0, m));
3195 } /* ng_btsocket_rfcomm_send_pn */
3198 * Calculate and send credits based on available space in receive buffer
3202 ng_btsocket_rfcomm_send_credits(ng_btsocket_rfcomm_pcb_p pcb)
3207 mtx_assert(&pcb->pcb_mtx, MA_OWNED);
3208 mtx_assert(&pcb->session->session_mtx, MA_OWNED);
3210 NG_BTSOCKET_RFCOMM_INFO(
3211 "%s: Sending more credits, dlci=%d, state=%d, flags=%#x, mtu=%d, " \
3212 "space=%ld, tx_cred=%d, rx_cred=%d\n",
3213 __func__, pcb->dlci, pcb->state, pcb->flags, pcb->mtu,
3214 sbspace(&pcb->so->so_rcv), pcb->tx_cred, pcb->rx_cred);
3216 credits = sbspace(&pcb->so->so_rcv) / pcb->mtu;
3218 if (pcb->rx_cred + credits > RFCOMM_MAX_CREDITS)
3219 credits = RFCOMM_MAX_CREDITS - pcb->rx_cred;
3221 error = ng_btsocket_rfcomm_send_uih(
3223 RFCOMM_MKADDRESS(INITIATOR(pcb->session),
3224 pcb->dlci), 1, credits, NULL);
3226 pcb->rx_cred += credits;
3228 NG_BTSOCKET_RFCOMM_INFO(
3229 "%s: Gave remote side %d more credits, dlci=%d, state=%d, flags=%#x, " \
3230 "rx_cred=%d, tx_cred=%d\n", __func__, credits, pcb->dlci, pcb->state,
3231 pcb->flags, pcb->rx_cred, pcb->tx_cred);
3233 NG_BTSOCKET_RFCOMM_ERR(
3234 "%s: Could not send credits, error=%d, dlci=%d, state=%d, flags=%#x, " \
3235 "mtu=%d, space=%ld, tx_cred=%d, rx_cred=%d\n",
3236 __func__, error, pcb->dlci, pcb->state,
3237 pcb->flags, pcb->mtu, sbspace(&pcb->so->so_rcv),
3238 pcb->tx_cred, pcb->rx_cred);
3242 } /* ng_btsocket_rfcomm_send_credits */
3244 /*****************************************************************************
3245 *****************************************************************************
3247 *****************************************************************************
3248 *****************************************************************************/
3251 * Send data from socket send buffer
3252 * Caller must hold pcb->pcb_mtx and pcb->session->session_mtx
3256 ng_btsocket_rfcomm_pcb_send(ng_btsocket_rfcomm_pcb_p pcb, int limit)
3258 struct mbuf *m = NULL;
3259 int sent, length, error;
3261 mtx_assert(&pcb->session->session_mtx, MA_OWNED);
3262 mtx_assert(&pcb->pcb_mtx, MA_OWNED);
3264 if (pcb->flags & NG_BTSOCKET_RFCOMM_DLC_CFC)
3265 limit = min(limit, pcb->tx_cred);
3266 else if (!(pcb->rmodem & RFCOMM_MODEM_FC))
3267 limit = min(limit, RFCOMM_MAX_CREDITS); /* XXX ??? */
3272 NG_BTSOCKET_RFCOMM_INFO(
3273 "%s: Could not send - remote flow control asserted, dlci=%d, flags=%#x, " \
3274 "rmodem=%#x, tx_cred=%d\n",
3275 __func__, pcb->dlci, pcb->flags, pcb->rmodem,
3281 for (error = 0, sent = 0; sent < limit; sent ++) {
3282 length = min(pcb->mtu, pcb->so->so_snd.sb_cc);
3286 /* Get the chunk from the socket's send buffer */
3287 m = ng_btsocket_rfcomm_prepare_packet(&pcb->so->so_snd, length);
3293 sbdrop(&pcb->so->so_snd, length);
3295 error = ng_btsocket_rfcomm_send_uih(pcb->session,
3296 RFCOMM_MKADDRESS(INITIATOR(pcb->session),
3297 pcb->dlci), 0, 0, m);
3302 if (pcb->flags & NG_BTSOCKET_RFCOMM_DLC_CFC)
3303 pcb->tx_cred -= sent;
3305 if (error == 0 && sent > 0) {
3306 pcb->flags &= ~NG_BTSOCKET_RFCOMM_DLC_SENDING;
3311 } /* ng_btsocket_rfcomm_pcb_send */
3314 * Unlink and disconnect DLC. If ng_btsocket_rfcomm_pcb_kill() returns
3315 * non zero value than socket has no reference and has to be detached.
3316 * Caller must hold pcb->pcb_mtx and pcb->session->session_mtx
3320 ng_btsocket_rfcomm_pcb_kill(ng_btsocket_rfcomm_pcb_p pcb, int error)
3322 ng_btsocket_rfcomm_session_p s = pcb->session;
3324 NG_BTSOCKET_RFCOMM_INFO(
3325 "%s: Killing DLC, so=%p, dlci=%d, state=%d, flags=%#x, error=%d\n",
3326 __func__, pcb->so, pcb->dlci, pcb->state, pcb->flags, error);
3328 if (pcb->session == NULL)
3329 panic("%s: DLC without session, pcb=%p, state=%d, flags=%#x\n",
3330 __func__, pcb, pcb->state, pcb->flags);
3332 mtx_assert(&pcb->session->session_mtx, MA_OWNED);
3333 mtx_assert(&pcb->pcb_mtx, MA_OWNED);
3335 if (pcb->flags & NG_BTSOCKET_RFCOMM_DLC_TIMO)
3336 ng_btsocket_rfcomm_untimeout(pcb);
3338 /* Detach DLC from the session. Does not matter which state DLC in */
3339 LIST_REMOVE(pcb, session_next);
3340 pcb->session = NULL;
3342 /* Change DLC state and wakeup all sleepers */
3343 pcb->state = NG_BTSOCKET_RFCOMM_DLC_CLOSED;
3344 pcb->so->so_error = error;
3345 soisdisconnected(pcb->so);
3346 wakeup(&pcb->state);
3348 /* Check if we have any DLCs left on the session */
3349 if (LIST_EMPTY(&s->dlcs) && INITIATOR(s)) {
3350 NG_BTSOCKET_RFCOMM_INFO(
3351 "%s: Disconnecting session, state=%d, flags=%#x, mtu=%d\n",
3352 __func__, s->state, s->flags, s->mtu);
3355 case NG_BTSOCKET_RFCOMM_SESSION_CLOSED:
3356 case NG_BTSOCKET_RFCOMM_SESSION_DISCONNECTING:
3358 * Do not have to do anything here. We can get here
3359 * when L2CAP connection was terminated or we have
3360 * received DISC on multiplexor channel
3364 case NG_BTSOCKET_RFCOMM_SESSION_OPEN:
3365 /* Send DISC on multiplexor channel */
3366 error = ng_btsocket_rfcomm_send_command(s,
3367 RFCOMM_FRAME_DISC, 0);
3369 s->state = NG_BTSOCKET_RFCOMM_SESSION_DISCONNECTING;
3374 case NG_BTSOCKET_RFCOMM_SESSION_CONNECTING:
3375 case NG_BTSOCKET_RFCOMM_SESSION_CONNECTED:
3376 s->state = NG_BTSOCKET_RFCOMM_SESSION_CLOSED;
3379 /* case NG_BTSOCKET_RFCOMM_SESSION_LISTENING: */
3381 panic("%s: Invalid session state=%d, flags=%#x\n",
3382 __func__, s->state, s->flags);
3386 ng_btsocket_rfcomm_task_wakeup();
3388 } /* ng_btsocket_rfcomm_pcb_kill */
3391 * Look for given dlci for given RFCOMM session. Caller must hold s->session_mtx
3394 static ng_btsocket_rfcomm_pcb_p
3395 ng_btsocket_rfcomm_pcb_by_dlci(ng_btsocket_rfcomm_session_p s, int dlci)
3397 ng_btsocket_rfcomm_pcb_p pcb = NULL;
3399 mtx_assert(&s->session_mtx, MA_OWNED);
3401 LIST_FOREACH(pcb, &s->dlcs, session_next)
3402 if (pcb->dlci == dlci)
3406 } /* ng_btsocket_rfcomm_pcb_by_dlci */
3409 * Look for socket that listens on given src address and given channel
3412 static ng_btsocket_rfcomm_pcb_p
3413 ng_btsocket_rfcomm_pcb_listener(bdaddr_p src, int channel)
3415 ng_btsocket_rfcomm_pcb_p pcb = NULL, pcb1 = NULL;
3417 mtx_lock(&ng_btsocket_rfcomm_sockets_mtx);
3419 LIST_FOREACH(pcb, &ng_btsocket_rfcomm_sockets, next) {
3420 if (pcb->channel != channel ||
3421 !(pcb->so->so_options & SO_ACCEPTCONN))
3424 if (bcmp(&pcb->src, src, sizeof(*src)) == 0)
3427 if (bcmp(&pcb->src, NG_HCI_BDADDR_ANY, sizeof(bdaddr_t)) == 0)
3431 mtx_unlock(&ng_btsocket_rfcomm_sockets_mtx);
3433 return ((pcb != NULL)? pcb : pcb1);
3434 } /* ng_btsocket_rfcomm_pcb_listener */
3436 /*****************************************************************************
3437 *****************************************************************************
3439 *****************************************************************************
3440 *****************************************************************************/
3443 * Set timeout. Caller MUST hold pcb_mtx
3447 ng_btsocket_rfcomm_timeout(ng_btsocket_rfcomm_pcb_p pcb)
3449 mtx_assert(&pcb->pcb_mtx, MA_OWNED);
3451 if (!(pcb->flags & NG_BTSOCKET_RFCOMM_DLC_TIMO)) {
3452 pcb->flags |= NG_BTSOCKET_RFCOMM_DLC_TIMO;
3453 pcb->flags &= ~NG_BTSOCKET_RFCOMM_DLC_TIMEDOUT;
3454 pcb->timo = timeout(ng_btsocket_rfcomm_process_timeout, pcb,
3455 ng_btsocket_rfcomm_timo * hz);
3457 panic("%s: Duplicated socket timeout?!\n", __func__);
3458 } /* ng_btsocket_rfcomm_timeout */
3461 * Unset pcb timeout. Caller MUST hold pcb_mtx
3465 ng_btsocket_rfcomm_untimeout(ng_btsocket_rfcomm_pcb_p pcb)
3467 mtx_assert(&pcb->pcb_mtx, MA_OWNED);
3469 if (pcb->flags & NG_BTSOCKET_RFCOMM_DLC_TIMO) {
3470 untimeout(ng_btsocket_rfcomm_process_timeout, pcb, pcb->timo);
3471 pcb->flags &= ~NG_BTSOCKET_RFCOMM_DLC_TIMO;
3472 pcb->flags &= ~NG_BTSOCKET_RFCOMM_DLC_TIMEDOUT;
3474 panic("%s: No socket timeout?!\n", __func__);
3475 } /* ng_btsocket_rfcomm_timeout */
3478 * Process pcb timeout
3482 ng_btsocket_rfcomm_process_timeout(void *xpcb)
3484 ng_btsocket_rfcomm_pcb_p pcb = (ng_btsocket_rfcomm_pcb_p) xpcb;
3486 mtx_lock(&pcb->pcb_mtx);
3488 NG_BTSOCKET_RFCOMM_INFO(
3489 "%s: Timeout, so=%p, dlci=%d, state=%d, flags=%#x\n",
3490 __func__, pcb->so, pcb->dlci, pcb->state, pcb->flags);
3492 pcb->flags &= ~NG_BTSOCKET_RFCOMM_DLC_TIMO;
3493 pcb->flags |= NG_BTSOCKET_RFCOMM_DLC_TIMEDOUT;
3495 switch (pcb->state) {
3496 case NG_BTSOCKET_RFCOMM_DLC_CONFIGURING:
3497 case NG_BTSOCKET_RFCOMM_DLC_CONNECTING:
3498 pcb->state = NG_BTSOCKET_RFCOMM_DLC_DISCONNECTING;
3501 case NG_BTSOCKET_RFCOMM_DLC_W4_CONNECT:
3502 case NG_BTSOCKET_RFCOMM_DLC_DISCONNECTING:
3507 "%s: DLC timeout in invalid state, dlci=%d, state=%d, flags=%#x\n",
3508 __func__, pcb->dlci, pcb->state, pcb->flags);
3512 ng_btsocket_rfcomm_task_wakeup();
3514 mtx_unlock(&pcb->pcb_mtx);
3515 } /* ng_btsocket_rfcomm_process_timeout */
3518 * Get up to length bytes from the socket buffer
3521 static struct mbuf *
3522 ng_btsocket_rfcomm_prepare_packet(struct sockbuf *sb, int length)
3524 struct mbuf *top = NULL, *m = NULL, *n = NULL, *nextpkt = NULL;
3525 int mlen, noff, len;
3527 MGETHDR(top, M_NOWAIT, MT_DATA);
3531 top->m_pkthdr.len = length;
3537 nextpkt = n->m_nextpkt;
3540 while (length > 0 && n != NULL) {
3541 len = min(mlen - m->m_len, n->m_len - noff);
3545 bcopy(mtod(n, caddr_t)+noff, mtod(m, caddr_t)+m->m_len, len);
3550 if (length > 0 && m->m_len == mlen) {
3551 MGET(m->m_next, M_NOWAIT, MT_DATA);
3552 if (m->m_next == NULL) {
3562 if (noff == n->m_len) {
3569 nextpkt = (n != NULL)? n->m_nextpkt : NULL;
3574 panic("%s: length=%d\n", __func__, length);
3575 if (length > 0 && n == NULL)
3576 panic("%s: bogus length=%d, n=%p\n", __func__, length, n);
3579 } /* ng_btsocket_rfcomm_prepare_packet */