6 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
8 * Copyright (c) 2001-2003 Maksim Yevmenkin <m_evmenkin@yahoo.com>
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
20 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 * $Id: ng_btsocket_rfcomm.c,v 1.28 2003/09/14 23:29:06 max Exp $
36 #include <sys/param.h>
37 #include <sys/systm.h>
38 #include <sys/bitstring.h>
39 #include <sys/domain.h>
40 #include <sys/endian.h>
41 #include <sys/errno.h>
42 #include <sys/filedesc.h>
43 #include <sys/ioccom.h>
44 #include <sys/kernel.h>
46 #include <sys/malloc.h>
48 #include <sys/mutex.h>
50 #include <sys/protosw.h>
51 #include <sys/queue.h>
52 #include <sys/socket.h>
53 #include <sys/socketvar.h>
54 #include <sys/sysctl.h>
55 #include <sys/taskqueue.h>
60 #include <netgraph/ng_message.h>
61 #include <netgraph/netgraph.h>
62 #include <netgraph/bluetooth/include/ng_bluetooth.h>
63 #include <netgraph/bluetooth/include/ng_hci.h>
64 #include <netgraph/bluetooth/include/ng_l2cap.h>
65 #include <netgraph/bluetooth/include/ng_btsocket.h>
66 #include <netgraph/bluetooth/include/ng_btsocket_l2cap.h>
67 #include <netgraph/bluetooth/include/ng_btsocket_rfcomm.h>
70 #ifdef NG_SEPARATE_MALLOC
71 static MALLOC_DEFINE(M_NETGRAPH_BTSOCKET_RFCOMM, "netgraph_btsocks_rfcomm",
72 "Netgraph Bluetooth RFCOMM sockets");
74 #define M_NETGRAPH_BTSOCKET_RFCOMM M_NETGRAPH
75 #endif /* NG_SEPARATE_MALLOC */
78 #define NG_BTSOCKET_RFCOMM_INFO \
79 if (ng_btsocket_rfcomm_debug_level >= NG_BTSOCKET_INFO_LEVEL && \
80 ppsratecheck(&ng_btsocket_rfcomm_lasttime, &ng_btsocket_rfcomm_curpps, 1)) \
83 #define NG_BTSOCKET_RFCOMM_WARN \
84 if (ng_btsocket_rfcomm_debug_level >= NG_BTSOCKET_WARN_LEVEL && \
85 ppsratecheck(&ng_btsocket_rfcomm_lasttime, &ng_btsocket_rfcomm_curpps, 1)) \
88 #define NG_BTSOCKET_RFCOMM_ERR \
89 if (ng_btsocket_rfcomm_debug_level >= NG_BTSOCKET_ERR_LEVEL && \
90 ppsratecheck(&ng_btsocket_rfcomm_lasttime, &ng_btsocket_rfcomm_curpps, 1)) \
93 #define NG_BTSOCKET_RFCOMM_ALERT \
94 if (ng_btsocket_rfcomm_debug_level >= NG_BTSOCKET_ALERT_LEVEL && \
95 ppsratecheck(&ng_btsocket_rfcomm_lasttime, &ng_btsocket_rfcomm_curpps, 1)) \
100 /* Local prototypes */
101 static int ng_btsocket_rfcomm_upcall
102 (struct socket *so, void *arg, int waitflag);
103 static void ng_btsocket_rfcomm_sessions_task
104 (void *ctx, int pending);
105 static void ng_btsocket_rfcomm_session_task
106 (ng_btsocket_rfcomm_session_p s);
107 #define ng_btsocket_rfcomm_task_wakeup() \
108 taskqueue_enqueue(taskqueue_swi_giant, &ng_btsocket_rfcomm_task)
110 static ng_btsocket_rfcomm_pcb_p ng_btsocket_rfcomm_connect_ind
111 (ng_btsocket_rfcomm_session_p s, int channel);
112 static void ng_btsocket_rfcomm_connect_cfm
113 (ng_btsocket_rfcomm_session_p s);
115 static int ng_btsocket_rfcomm_session_create
116 (ng_btsocket_rfcomm_session_p *sp, struct socket *l2so,
117 bdaddr_p src, bdaddr_p dst, struct thread *td);
118 static int ng_btsocket_rfcomm_session_accept
119 (ng_btsocket_rfcomm_session_p s0);
120 static int ng_btsocket_rfcomm_session_connect
121 (ng_btsocket_rfcomm_session_p s);
122 static int ng_btsocket_rfcomm_session_receive
123 (ng_btsocket_rfcomm_session_p s);
124 static int ng_btsocket_rfcomm_session_send
125 (ng_btsocket_rfcomm_session_p s);
126 static void ng_btsocket_rfcomm_session_clean
127 (ng_btsocket_rfcomm_session_p s);
128 static void ng_btsocket_rfcomm_session_process_pcb
129 (ng_btsocket_rfcomm_session_p s);
130 static ng_btsocket_rfcomm_session_p ng_btsocket_rfcomm_session_by_addr
131 (bdaddr_p src, bdaddr_p dst);
133 static int ng_btsocket_rfcomm_receive_frame
134 (ng_btsocket_rfcomm_session_p s, struct mbuf *m0);
135 static int ng_btsocket_rfcomm_receive_sabm
136 (ng_btsocket_rfcomm_session_p s, int dlci);
137 static int ng_btsocket_rfcomm_receive_disc
138 (ng_btsocket_rfcomm_session_p s, int dlci);
139 static int ng_btsocket_rfcomm_receive_ua
140 (ng_btsocket_rfcomm_session_p s, int dlci);
141 static int ng_btsocket_rfcomm_receive_dm
142 (ng_btsocket_rfcomm_session_p s, int dlci);
143 static int ng_btsocket_rfcomm_receive_uih
144 (ng_btsocket_rfcomm_session_p s, int dlci, int pf, struct mbuf *m0);
145 static int ng_btsocket_rfcomm_receive_mcc
146 (ng_btsocket_rfcomm_session_p s, struct mbuf *m0);
147 static int ng_btsocket_rfcomm_receive_test
148 (ng_btsocket_rfcomm_session_p s, struct mbuf *m0);
149 static int ng_btsocket_rfcomm_receive_fc
150 (ng_btsocket_rfcomm_session_p s, struct mbuf *m0);
151 static int ng_btsocket_rfcomm_receive_msc
152 (ng_btsocket_rfcomm_session_p s, struct mbuf *m0);
153 static int ng_btsocket_rfcomm_receive_rpn
154 (ng_btsocket_rfcomm_session_p s, struct mbuf *m0);
155 static int ng_btsocket_rfcomm_receive_rls
156 (ng_btsocket_rfcomm_session_p s, struct mbuf *m0);
157 static int ng_btsocket_rfcomm_receive_pn
158 (ng_btsocket_rfcomm_session_p s, struct mbuf *m0);
159 static void ng_btsocket_rfcomm_set_pn
160 (ng_btsocket_rfcomm_pcb_p pcb, u_int8_t cr, u_int8_t flow_control,
161 u_int8_t credits, u_int16_t mtu);
163 static int ng_btsocket_rfcomm_send_command
164 (ng_btsocket_rfcomm_session_p s, u_int8_t type, u_int8_t dlci);
165 static int ng_btsocket_rfcomm_send_uih
166 (ng_btsocket_rfcomm_session_p s, u_int8_t address, u_int8_t pf,
167 u_int8_t credits, struct mbuf *data);
168 static int ng_btsocket_rfcomm_send_msc
169 (ng_btsocket_rfcomm_pcb_p pcb);
170 static int ng_btsocket_rfcomm_send_pn
171 (ng_btsocket_rfcomm_pcb_p pcb);
172 static int ng_btsocket_rfcomm_send_credits
173 (ng_btsocket_rfcomm_pcb_p pcb);
175 static int ng_btsocket_rfcomm_pcb_send
176 (ng_btsocket_rfcomm_pcb_p pcb, int limit);
177 static void ng_btsocket_rfcomm_pcb_kill
178 (ng_btsocket_rfcomm_pcb_p pcb, int error);
179 static ng_btsocket_rfcomm_pcb_p ng_btsocket_rfcomm_pcb_by_dlci
180 (ng_btsocket_rfcomm_session_p s, int dlci);
181 static ng_btsocket_rfcomm_pcb_p ng_btsocket_rfcomm_pcb_listener
182 (bdaddr_p src, int channel);
184 static void ng_btsocket_rfcomm_timeout
185 (ng_btsocket_rfcomm_pcb_p pcb);
186 static void ng_btsocket_rfcomm_untimeout
187 (ng_btsocket_rfcomm_pcb_p pcb);
188 static void ng_btsocket_rfcomm_process_timeout
191 static struct mbuf * ng_btsocket_rfcomm_prepare_packet
192 (struct sockbuf *sb, int length);
195 extern int ifqmaxlen;
196 static u_int32_t ng_btsocket_rfcomm_debug_level;
197 static u_int32_t ng_btsocket_rfcomm_timo;
198 struct task ng_btsocket_rfcomm_task;
199 static LIST_HEAD(, ng_btsocket_rfcomm_session) ng_btsocket_rfcomm_sessions;
200 static struct mtx ng_btsocket_rfcomm_sessions_mtx;
201 static LIST_HEAD(, ng_btsocket_rfcomm_pcb) ng_btsocket_rfcomm_sockets;
202 static struct mtx ng_btsocket_rfcomm_sockets_mtx;
203 static struct timeval ng_btsocket_rfcomm_lasttime;
204 static int ng_btsocket_rfcomm_curpps;
207 SYSCTL_DECL(_net_bluetooth_rfcomm_sockets);
208 static SYSCTL_NODE(_net_bluetooth_rfcomm_sockets, OID_AUTO, stream, CTLFLAG_RW,
209 0, "Bluetooth STREAM RFCOMM sockets family");
210 SYSCTL_UINT(_net_bluetooth_rfcomm_sockets_stream, OID_AUTO, debug_level,
212 &ng_btsocket_rfcomm_debug_level, NG_BTSOCKET_INFO_LEVEL,
213 "Bluetooth STREAM RFCOMM sockets debug level");
214 SYSCTL_UINT(_net_bluetooth_rfcomm_sockets_stream, OID_AUTO, timeout,
216 &ng_btsocket_rfcomm_timo, 60,
217 "Bluetooth STREAM RFCOMM sockets timeout");
219 /*****************************************************************************
220 *****************************************************************************
222 *****************************************************************************
223 *****************************************************************************/
225 static u_int8_t ng_btsocket_rfcomm_crc_table[256] = {
226 0x00, 0x91, 0xe3, 0x72, 0x07, 0x96, 0xe4, 0x75,
227 0x0e, 0x9f, 0xed, 0x7c, 0x09, 0x98, 0xea, 0x7b,
228 0x1c, 0x8d, 0xff, 0x6e, 0x1b, 0x8a, 0xf8, 0x69,
229 0x12, 0x83, 0xf1, 0x60, 0x15, 0x84, 0xf6, 0x67,
231 0x38, 0xa9, 0xdb, 0x4a, 0x3f, 0xae, 0xdc, 0x4d,
232 0x36, 0xa7, 0xd5, 0x44, 0x31, 0xa0, 0xd2, 0x43,
233 0x24, 0xb5, 0xc7, 0x56, 0x23, 0xb2, 0xc0, 0x51,
234 0x2a, 0xbb, 0xc9, 0x58, 0x2d, 0xbc, 0xce, 0x5f,
236 0x70, 0xe1, 0x93, 0x02, 0x77, 0xe6, 0x94, 0x05,
237 0x7e, 0xef, 0x9d, 0x0c, 0x79, 0xe8, 0x9a, 0x0b,
238 0x6c, 0xfd, 0x8f, 0x1e, 0x6b, 0xfa, 0x88, 0x19,
239 0x62, 0xf3, 0x81, 0x10, 0x65, 0xf4, 0x86, 0x17,
241 0x48, 0xd9, 0xab, 0x3a, 0x4f, 0xde, 0xac, 0x3d,
242 0x46, 0xd7, 0xa5, 0x34, 0x41, 0xd0, 0xa2, 0x33,
243 0x54, 0xc5, 0xb7, 0x26, 0x53, 0xc2, 0xb0, 0x21,
244 0x5a, 0xcb, 0xb9, 0x28, 0x5d, 0xcc, 0xbe, 0x2f,
246 0xe0, 0x71, 0x03, 0x92, 0xe7, 0x76, 0x04, 0x95,
247 0xee, 0x7f, 0x0d, 0x9c, 0xe9, 0x78, 0x0a, 0x9b,
248 0xfc, 0x6d, 0x1f, 0x8e, 0xfb, 0x6a, 0x18, 0x89,
249 0xf2, 0x63, 0x11, 0x80, 0xf5, 0x64, 0x16, 0x87,
251 0xd8, 0x49, 0x3b, 0xaa, 0xdf, 0x4e, 0x3c, 0xad,
252 0xd6, 0x47, 0x35, 0xa4, 0xd1, 0x40, 0x32, 0xa3,
253 0xc4, 0x55, 0x27, 0xb6, 0xc3, 0x52, 0x20, 0xb1,
254 0xca, 0x5b, 0x29, 0xb8, 0xcd, 0x5c, 0x2e, 0xbf,
256 0x90, 0x01, 0x73, 0xe2, 0x97, 0x06, 0x74, 0xe5,
257 0x9e, 0x0f, 0x7d, 0xec, 0x99, 0x08, 0x7a, 0xeb,
258 0x8c, 0x1d, 0x6f, 0xfe, 0x8b, 0x1a, 0x68, 0xf9,
259 0x82, 0x13, 0x61, 0xf0, 0x85, 0x14, 0x66, 0xf7,
261 0xa8, 0x39, 0x4b, 0xda, 0xaf, 0x3e, 0x4c, 0xdd,
262 0xa6, 0x37, 0x45, 0xd4, 0xa1, 0x30, 0x42, 0xd3,
263 0xb4, 0x25, 0x57, 0xc6, 0xb3, 0x22, 0x50, 0xc1,
264 0xba, 0x2b, 0x59, 0xc8, 0xbd, 0x2c, 0x5e, 0xcf
269 ng_btsocket_rfcomm_crc(u_int8_t *data, int length)
274 crc = ng_btsocket_rfcomm_crc_table[crc ^ *data++];
277 } /* ng_btsocket_rfcomm_crc */
281 ng_btsocket_rfcomm_fcs2(u_int8_t *data)
283 return (0xff - ng_btsocket_rfcomm_crc(data, 2));
284 } /* ng_btsocket_rfcomm_fcs2 */
288 ng_btsocket_rfcomm_fcs3(u_int8_t *data)
290 return (0xff - ng_btsocket_rfcomm_crc(data, 3));
291 } /* ng_btsocket_rfcomm_fcs3 */
296 * From Bluetooth spec
298 * "... In 07.10, the frame check sequence (FCS) is calculated on different
299 * sets of fields for different frame types. These are the fields that the
300 * FCS are calculated on:
302 * For SABM, DISC, UA, DM frames: on Address, Control and length field.
303 * For UIH frames: on Address and Control field.
305 * (This is stated here for clarification, and to set the standard for RFCOMM;
306 * the fields included in FCS calculation have actually changed in version
307 * 7.0.0 of TS 07.10, but RFCOMM will not change the FCS calculation scheme
308 * from the one above.) ..."
312 ng_btsocket_rfcomm_check_fcs(u_int8_t *data, int type, u_int8_t fcs)
314 if (type != RFCOMM_FRAME_UIH)
315 return (ng_btsocket_rfcomm_fcs3(data) != fcs);
317 return (ng_btsocket_rfcomm_fcs2(data) != fcs);
318 } /* ng_btsocket_rfcomm_check_fcs */
320 /*****************************************************************************
321 *****************************************************************************
323 *****************************************************************************
324 *****************************************************************************/
327 * Initialize everything
331 ng_btsocket_rfcomm_init(void)
334 /* Skip initialization of globals for non-default instances. */
335 if (!IS_DEFAULT_VNET(curvnet))
338 ng_btsocket_rfcomm_debug_level = NG_BTSOCKET_WARN_LEVEL;
339 ng_btsocket_rfcomm_timo = 60;
342 TASK_INIT(&ng_btsocket_rfcomm_task, 0,
343 ng_btsocket_rfcomm_sessions_task, NULL);
345 /* RFCOMM sessions list */
346 LIST_INIT(&ng_btsocket_rfcomm_sessions);
347 mtx_init(&ng_btsocket_rfcomm_sessions_mtx,
348 "btsocks_rfcomm_sessions_mtx", NULL, MTX_DEF);
350 /* RFCOMM sockets list */
351 LIST_INIT(&ng_btsocket_rfcomm_sockets);
352 mtx_init(&ng_btsocket_rfcomm_sockets_mtx,
353 "btsocks_rfcomm_sockets_mtx", NULL, MTX_DEF);
354 } /* ng_btsocket_rfcomm_init */
357 * Abort connection on socket
361 ng_btsocket_rfcomm_abort(struct socket *so)
364 so->so_error = ECONNABORTED;
365 (void)ng_btsocket_rfcomm_disconnect(so);
366 } /* ng_btsocket_rfcomm_abort */
369 ng_btsocket_rfcomm_close(struct socket *so)
372 (void)ng_btsocket_rfcomm_disconnect(so);
373 } /* ng_btsocket_rfcomm_close */
376 * Accept connection on socket. Nothing to do here, socket must be connected
377 * and ready, so just return peer address and be done with it.
381 ng_btsocket_rfcomm_accept(struct socket *so, struct sockaddr **nam)
383 return (ng_btsocket_rfcomm_peeraddr(so, nam));
384 } /* ng_btsocket_rfcomm_accept */
387 * Create and attach new socket
391 ng_btsocket_rfcomm_attach(struct socket *so, int proto, struct thread *td)
393 ng_btsocket_rfcomm_pcb_p pcb = so2rfcomm_pcb(so);
396 /* Check socket and protocol */
397 if (so->so_type != SOCK_STREAM)
398 return (ESOCKTNOSUPPORT);
400 #if 0 /* XXX sonewconn() calls "pru_attach" with proto == 0 */
402 if (proto != BLUETOOTH_PROTO_RFCOMM)
403 return (EPROTONOSUPPORT);
409 /* Reserve send and receive space if it is not reserved yet */
410 if ((so->so_snd.sb_hiwat == 0) || (so->so_rcv.sb_hiwat == 0)) {
411 error = soreserve(so, NG_BTSOCKET_RFCOMM_SENDSPACE,
412 NG_BTSOCKET_RFCOMM_RECVSPACE);
417 /* Allocate the PCB */
418 pcb = malloc(sizeof(*pcb),
419 M_NETGRAPH_BTSOCKET_RFCOMM, M_NOWAIT | M_ZERO);
423 /* Link the PCB and the socket */
424 so->so_pcb = (caddr_t) pcb;
428 pcb->state = NG_BTSOCKET_RFCOMM_DLC_CLOSED;
429 pcb->flags = NG_BTSOCKET_RFCOMM_DLC_CFC;
432 pcb->rmodem = (RFCOMM_MODEM_RTC | RFCOMM_MODEM_RTR | RFCOMM_MODEM_DV);
434 pcb->mtu = RFCOMM_DEFAULT_MTU;
436 pcb->rx_cred = RFCOMM_DEFAULT_CREDITS;
438 mtx_init(&pcb->pcb_mtx, "btsocks_rfcomm_pcb_mtx", NULL, MTX_DEF);
439 callout_init_mtx(&pcb->timo, &pcb->pcb_mtx, 0);
441 /* Add the PCB to the list */
442 mtx_lock(&ng_btsocket_rfcomm_sockets_mtx);
443 LIST_INSERT_HEAD(&ng_btsocket_rfcomm_sockets, pcb, next);
444 mtx_unlock(&ng_btsocket_rfcomm_sockets_mtx);
447 } /* ng_btsocket_rfcomm_attach */
454 ng_btsocket_rfcomm_bind(struct socket *so, struct sockaddr *nam,
457 ng_btsocket_rfcomm_pcb_t *pcb = so2rfcomm_pcb(so), *pcb1;
458 struct sockaddr_rfcomm *sa = (struct sockaddr_rfcomm *) nam;
466 if (sa->rfcomm_family != AF_BLUETOOTH)
467 return (EAFNOSUPPORT);
468 if (sa->rfcomm_len != sizeof(*sa))
470 if (sa->rfcomm_channel > 30)
473 mtx_lock(&pcb->pcb_mtx);
475 if (sa->rfcomm_channel != 0) {
476 mtx_lock(&ng_btsocket_rfcomm_sockets_mtx);
478 LIST_FOREACH(pcb1, &ng_btsocket_rfcomm_sockets, next) {
479 if (pcb1->channel == sa->rfcomm_channel &&
480 bcmp(&pcb1->src, &sa->rfcomm_bdaddr,
481 sizeof(pcb1->src)) == 0) {
482 mtx_unlock(&ng_btsocket_rfcomm_sockets_mtx);
483 mtx_unlock(&pcb->pcb_mtx);
489 mtx_unlock(&ng_btsocket_rfcomm_sockets_mtx);
492 bcopy(&sa->rfcomm_bdaddr, &pcb->src, sizeof(pcb->src));
493 pcb->channel = sa->rfcomm_channel;
495 mtx_unlock(&pcb->pcb_mtx);
498 } /* ng_btsocket_rfcomm_bind */
505 ng_btsocket_rfcomm_connect(struct socket *so, struct sockaddr *nam,
508 ng_btsocket_rfcomm_pcb_t *pcb = so2rfcomm_pcb(so);
509 struct sockaddr_rfcomm *sa = (struct sockaddr_rfcomm *) nam;
510 ng_btsocket_rfcomm_session_t *s = NULL;
511 struct socket *l2so = NULL;
520 if (sa->rfcomm_family != AF_BLUETOOTH)
521 return (EAFNOSUPPORT);
522 if (sa->rfcomm_len != sizeof(*sa))
524 if (sa->rfcomm_channel > 30)
526 if (sa->rfcomm_channel == 0 ||
527 bcmp(&sa->rfcomm_bdaddr, NG_HCI_BDADDR_ANY, sizeof(bdaddr_t)) == 0)
528 return (EDESTADDRREQ);
531 * Note that we will not check for errors in socreate() because
532 * if we failed to create L2CAP socket at this point we still
533 * might have already open session.
536 error = socreate(PF_BLUETOOTH, &l2so, SOCK_SEQPACKET,
537 BLUETOOTH_PROTO_L2CAP, td->td_ucred, td);
540 * Look for session between "pcb->src" and "sa->rfcomm_bdaddr" (dst)
543 mtx_lock(&ng_btsocket_rfcomm_sessions_mtx);
545 s = ng_btsocket_rfcomm_session_by_addr(&pcb->src, &sa->rfcomm_bdaddr);
548 * We need to create new RFCOMM session. Check if we have L2CAP
549 * socket. If l2so == NULL then error has the error code from
554 mtx_unlock(&ng_btsocket_rfcomm_sessions_mtx);
558 error = ng_btsocket_rfcomm_session_create(&s, l2so,
559 &pcb->src, &sa->rfcomm_bdaddr, td);
561 mtx_unlock(&ng_btsocket_rfcomm_sessions_mtx);
566 } else if (l2so != NULL)
567 soclose(l2so); /* we don't need new L2CAP socket */
570 * Check if we already have the same DLCI the same session
573 mtx_lock(&s->session_mtx);
574 mtx_lock(&pcb->pcb_mtx);
576 dlci = RFCOMM_MKDLCI(!INITIATOR(s), sa->rfcomm_channel);
578 if (ng_btsocket_rfcomm_pcb_by_dlci(s, dlci) != NULL) {
579 mtx_unlock(&pcb->pcb_mtx);
580 mtx_unlock(&s->session_mtx);
581 mtx_unlock(&ng_btsocket_rfcomm_sessions_mtx);
587 * Check session state and if its not acceptable then refuse connection
591 case NG_BTSOCKET_RFCOMM_SESSION_CONNECTING:
592 case NG_BTSOCKET_RFCOMM_SESSION_CONNECTED:
593 case NG_BTSOCKET_RFCOMM_SESSION_OPEN:
595 * Update destination address and channel and attach
599 bcopy(&sa->rfcomm_bdaddr, &pcb->dst, sizeof(pcb->dst));
600 pcb->channel = sa->rfcomm_channel;
603 LIST_INSERT_HEAD(&s->dlcs, pcb, session_next);
606 ng_btsocket_rfcomm_timeout(pcb);
607 soisconnecting(pcb->so);
609 if (s->state == NG_BTSOCKET_RFCOMM_SESSION_OPEN) {
611 bcopy(&so2l2cap_pcb(s->l2so)->src, &pcb->src,
614 pcb->state = NG_BTSOCKET_RFCOMM_DLC_CONFIGURING;
616 error = ng_btsocket_rfcomm_send_pn(pcb);
618 error = ng_btsocket_rfcomm_task_wakeup();
620 pcb->state = NG_BTSOCKET_RFCOMM_DLC_W4_CONNECT;
628 mtx_unlock(&pcb->pcb_mtx);
629 mtx_unlock(&s->session_mtx);
630 mtx_unlock(&ng_btsocket_rfcomm_sessions_mtx);
633 } /* ng_btsocket_rfcomm_connect */
636 * Process ioctl's calls on socket.
637 * XXX FIXME this should provide interface to the RFCOMM multiplexor channel
641 ng_btsocket_rfcomm_control(struct socket *so, u_long cmd, caddr_t data,
642 struct ifnet *ifp, struct thread *td)
645 } /* ng_btsocket_rfcomm_control */
648 * Process getsockopt/setsockopt system calls
652 ng_btsocket_rfcomm_ctloutput(struct socket *so, struct sockopt *sopt)
654 ng_btsocket_rfcomm_pcb_p pcb = so2rfcomm_pcb(so);
655 struct ng_btsocket_rfcomm_fc_info fcinfo;
660 if (sopt->sopt_level != SOL_RFCOMM)
663 mtx_lock(&pcb->pcb_mtx);
665 switch (sopt->sopt_dir) {
667 switch (sopt->sopt_name) {
669 error = sooptcopyout(sopt, &pcb->mtu, sizeof(pcb->mtu));
672 case SO_RFCOMM_FC_INFO:
673 fcinfo.lmodem = pcb->lmodem;
674 fcinfo.rmodem = pcb->rmodem;
675 fcinfo.tx_cred = pcb->tx_cred;
676 fcinfo.rx_cred = pcb->rx_cred;
677 fcinfo.cfc = (pcb->flags & NG_BTSOCKET_RFCOMM_DLC_CFC)?
681 error = sooptcopyout(sopt, &fcinfo, sizeof(fcinfo));
691 switch (sopt->sopt_name) {
703 mtx_unlock(&pcb->pcb_mtx);
706 } /* ng_btsocket_rfcomm_ctloutput */
709 * Detach and destroy socket
713 ng_btsocket_rfcomm_detach(struct socket *so)
715 ng_btsocket_rfcomm_pcb_p pcb = so2rfcomm_pcb(so);
717 KASSERT(pcb != NULL, ("ng_btsocket_rfcomm_detach: pcb == NULL"));
719 mtx_lock(&pcb->pcb_mtx);
721 switch (pcb->state) {
722 case NG_BTSOCKET_RFCOMM_DLC_W4_CONNECT:
723 case NG_BTSOCKET_RFCOMM_DLC_CONFIGURING:
724 case NG_BTSOCKET_RFCOMM_DLC_CONNECTING:
725 case NG_BTSOCKET_RFCOMM_DLC_CONNECTED:
726 /* XXX What to do with pending request? */
727 if (pcb->flags & NG_BTSOCKET_RFCOMM_DLC_TIMO)
728 ng_btsocket_rfcomm_untimeout(pcb);
730 if (pcb->state == NG_BTSOCKET_RFCOMM_DLC_W4_CONNECT)
731 pcb->flags |= NG_BTSOCKET_RFCOMM_DLC_DETACHED;
733 pcb->state = NG_BTSOCKET_RFCOMM_DLC_DISCONNECTING;
735 ng_btsocket_rfcomm_task_wakeup();
738 case NG_BTSOCKET_RFCOMM_DLC_DISCONNECTING:
739 ng_btsocket_rfcomm_task_wakeup();
743 while (pcb->state != NG_BTSOCKET_RFCOMM_DLC_CLOSED)
744 msleep(&pcb->state, &pcb->pcb_mtx, PZERO, "rf_det", 0);
746 if (pcb->session != NULL)
747 panic("%s: pcb->session != NULL\n", __func__);
748 if (pcb->flags & NG_BTSOCKET_RFCOMM_DLC_TIMO)
749 panic("%s: timeout on closed DLC, flags=%#x\n",
750 __func__, pcb->flags);
752 mtx_lock(&ng_btsocket_rfcomm_sockets_mtx);
753 LIST_REMOVE(pcb, next);
754 mtx_unlock(&ng_btsocket_rfcomm_sockets_mtx);
756 mtx_unlock(&pcb->pcb_mtx);
758 mtx_destroy(&pcb->pcb_mtx);
759 bzero(pcb, sizeof(*pcb));
760 free(pcb, M_NETGRAPH_BTSOCKET_RFCOMM);
762 soisdisconnected(so);
764 } /* ng_btsocket_rfcomm_detach */
771 ng_btsocket_rfcomm_disconnect(struct socket *so)
773 ng_btsocket_rfcomm_pcb_p pcb = so2rfcomm_pcb(so);
778 mtx_lock(&pcb->pcb_mtx);
780 if (pcb->state == NG_BTSOCKET_RFCOMM_DLC_DISCONNECTING) {
781 mtx_unlock(&pcb->pcb_mtx);
782 return (EINPROGRESS);
785 /* XXX What to do with pending request? */
786 if (pcb->flags & NG_BTSOCKET_RFCOMM_DLC_TIMO)
787 ng_btsocket_rfcomm_untimeout(pcb);
789 switch (pcb->state) {
790 case NG_BTSOCKET_RFCOMM_DLC_CONFIGURING: /* XXX can we get here? */
791 case NG_BTSOCKET_RFCOMM_DLC_CONNECTING: /* XXX can we get here? */
792 case NG_BTSOCKET_RFCOMM_DLC_CONNECTED:
795 * Just change DLC state and enqueue RFCOMM task. It will
796 * queue and send DISC on the DLC.
799 pcb->state = NG_BTSOCKET_RFCOMM_DLC_DISCONNECTING;
800 soisdisconnecting(so);
802 ng_btsocket_rfcomm_task_wakeup();
805 case NG_BTSOCKET_RFCOMM_DLC_CLOSED:
806 case NG_BTSOCKET_RFCOMM_DLC_W4_CONNECT:
810 panic("%s: Invalid DLC state=%d, flags=%#x\n",
811 __func__, pcb->state, pcb->flags);
815 mtx_unlock(&pcb->pcb_mtx);
818 } /* ng_btsocket_rfcomm_disconnect */
821 * Listen on socket. First call to listen() will create listening RFCOMM session
825 ng_btsocket_rfcomm_listen(struct socket *so, int backlog, struct thread *td)
827 ng_btsocket_rfcomm_pcb_p pcb = so2rfcomm_pcb(so), pcb1;
828 ng_btsocket_rfcomm_session_p s = NULL;
829 struct socket *l2so = NULL;
830 int error, socreate_error, usedchannels;
834 if (pcb->channel > 30)
835 return (EADDRNOTAVAIL);
839 mtx_lock(&pcb->pcb_mtx);
841 if (pcb->channel == 0) {
842 mtx_lock(&ng_btsocket_rfcomm_sockets_mtx);
844 LIST_FOREACH(pcb1, &ng_btsocket_rfcomm_sockets, next)
845 if (pcb1->channel != 0 &&
846 bcmp(&pcb1->src, &pcb->src, sizeof(pcb->src)) == 0)
847 usedchannels |= (1 << (pcb1->channel - 1));
849 for (pcb->channel = 30; pcb->channel > 0; pcb->channel --)
850 if (!(usedchannels & (1 << (pcb->channel - 1))))
853 if (pcb->channel == 0) {
854 mtx_unlock(&ng_btsocket_rfcomm_sockets_mtx);
855 mtx_unlock(&pcb->pcb_mtx);
857 return (EADDRNOTAVAIL);
860 mtx_unlock(&ng_btsocket_rfcomm_sockets_mtx);
863 mtx_unlock(&pcb->pcb_mtx);
866 * Note that we will not check for errors in socreate() because
867 * if we failed to create L2CAP socket at this point we still
868 * might have already open session.
871 socreate_error = socreate(PF_BLUETOOTH, &l2so, SOCK_SEQPACKET,
872 BLUETOOTH_PROTO_L2CAP, td->td_ucred, td);
875 * Transition the socket and session into the LISTENING state. Check
876 * for collisions first, as there can only be one.
878 mtx_lock(&ng_btsocket_rfcomm_sessions_mtx);
880 error = solisten_proto_check(so);
885 LIST_FOREACH(s, &ng_btsocket_rfcomm_sessions, next)
886 if (s->state == NG_BTSOCKET_RFCOMM_SESSION_LISTENING)
891 * We need to create default RFCOMM session. Check if we have
892 * L2CAP socket. If l2so == NULL then error has the error code
896 error = socreate_error;
901 * Create default listen RFCOMM session. The default RFCOMM
902 * session will listen on ANY address.
904 * XXX FIXME Note that currently there is no way to adjust MTU
905 * for the default session.
907 error = ng_btsocket_rfcomm_session_create(&s, l2so,
908 NG_HCI_BDADDR_ANY, NULL, td);
914 solisten_proto(so, backlog);
917 mtx_unlock(&ng_btsocket_rfcomm_sessions_mtx);
919 * If we still have an l2so reference here, it's unneeded, so release
925 } /* ng_btsocket_listen */
932 ng_btsocket_rfcomm_peeraddr(struct socket *so, struct sockaddr **nam)
934 ng_btsocket_rfcomm_pcb_p pcb = so2rfcomm_pcb(so);
935 struct sockaddr_rfcomm sa;
940 bcopy(&pcb->dst, &sa.rfcomm_bdaddr, sizeof(sa.rfcomm_bdaddr));
941 sa.rfcomm_channel = pcb->channel;
942 sa.rfcomm_len = sizeof(sa);
943 sa.rfcomm_family = AF_BLUETOOTH;
945 *nam = sodupsockaddr((struct sockaddr *) &sa, M_NOWAIT);
947 return ((*nam == NULL)? ENOMEM : 0);
948 } /* ng_btsocket_rfcomm_peeraddr */
951 * Send data to socket
955 ng_btsocket_rfcomm_send(struct socket *so, int flags, struct mbuf *m,
956 struct sockaddr *nam, struct mbuf *control, struct thread *td)
958 ng_btsocket_rfcomm_pcb_t *pcb = so2rfcomm_pcb(so);
961 /* Check socket and input */
962 if (pcb == NULL || m == NULL || control != NULL) {
967 mtx_lock(&pcb->pcb_mtx);
969 /* Make sure DLC is connected */
970 if (pcb->state != NG_BTSOCKET_RFCOMM_DLC_CONNECTED) {
971 mtx_unlock(&pcb->pcb_mtx);
976 /* Put the packet on the socket's send queue and wakeup RFCOMM task */
977 sbappend(&pcb->so->so_snd, m, flags);
980 if (!(pcb->flags & NG_BTSOCKET_RFCOMM_DLC_SENDING)) {
981 pcb->flags |= NG_BTSOCKET_RFCOMM_DLC_SENDING;
982 error = ng_btsocket_rfcomm_task_wakeup();
985 mtx_unlock(&pcb->pcb_mtx);
987 NG_FREE_M(m); /* checks for != NULL */
991 } /* ng_btsocket_rfcomm_send */
998 ng_btsocket_rfcomm_sockaddr(struct socket *so, struct sockaddr **nam)
1000 ng_btsocket_rfcomm_pcb_p pcb = so2rfcomm_pcb(so);
1001 struct sockaddr_rfcomm sa;
1006 bcopy(&pcb->src, &sa.rfcomm_bdaddr, sizeof(sa.rfcomm_bdaddr));
1007 sa.rfcomm_channel = pcb->channel;
1008 sa.rfcomm_len = sizeof(sa);
1009 sa.rfcomm_family = AF_BLUETOOTH;
1011 *nam = sodupsockaddr((struct sockaddr *) &sa, M_NOWAIT);
1013 return ((*nam == NULL)? ENOMEM : 0);
1014 } /* ng_btsocket_rfcomm_sockaddr */
1017 * Upcall function for L2CAP sockets. Enqueue RFCOMM task.
1021 ng_btsocket_rfcomm_upcall(struct socket *so, void *arg, int waitflag)
1026 panic("%s: so == NULL\n", __func__);
1028 if ((error = ng_btsocket_rfcomm_task_wakeup()) != 0)
1029 NG_BTSOCKET_RFCOMM_ALERT(
1030 "%s: Could not enqueue RFCOMM task, error=%d\n", __func__, error);
1032 } /* ng_btsocket_rfcomm_upcall */
1035 * RFCOMM task. Will handle all RFCOMM sessions in one pass.
1036 * XXX FIXME does not scale very well
1040 ng_btsocket_rfcomm_sessions_task(void *ctx, int pending)
1042 ng_btsocket_rfcomm_session_p s = NULL, s_next = NULL;
1044 mtx_lock(&ng_btsocket_rfcomm_sessions_mtx);
1046 for (s = LIST_FIRST(&ng_btsocket_rfcomm_sessions); s != NULL; ) {
1047 mtx_lock(&s->session_mtx);
1048 s_next = LIST_NEXT(s, next);
1050 ng_btsocket_rfcomm_session_task(s);
1052 if (s->state == NG_BTSOCKET_RFCOMM_SESSION_CLOSED) {
1053 /* Unlink and clean the session */
1054 LIST_REMOVE(s, next);
1056 NG_BT_MBUFQ_DRAIN(&s->outq);
1057 if (!LIST_EMPTY(&s->dlcs))
1058 panic("%s: DLC list is not empty\n", __func__);
1060 /* Close L2CAP socket */
1061 SOCKBUF_LOCK(&s->l2so->so_rcv);
1062 soupcall_clear(s->l2so, SO_RCV);
1063 SOCKBUF_UNLOCK(&s->l2so->so_rcv);
1064 SOCKBUF_LOCK(&s->l2so->so_snd);
1065 soupcall_clear(s->l2so, SO_SND);
1066 SOCKBUF_UNLOCK(&s->l2so->so_snd);
1069 mtx_unlock(&s->session_mtx);
1071 mtx_destroy(&s->session_mtx);
1072 bzero(s, sizeof(*s));
1073 free(s, M_NETGRAPH_BTSOCKET_RFCOMM);
1075 mtx_unlock(&s->session_mtx);
1080 mtx_unlock(&ng_btsocket_rfcomm_sessions_mtx);
1081 } /* ng_btsocket_rfcomm_sessions_task */
1084 * Process RFCOMM session. Will handle all RFCOMM sockets in one pass.
1088 ng_btsocket_rfcomm_session_task(ng_btsocket_rfcomm_session_p s)
1090 mtx_assert(&s->session_mtx, MA_OWNED);
1092 if (s->l2so->so_rcv.sb_state & SBS_CANTRCVMORE) {
1093 NG_BTSOCKET_RFCOMM_INFO(
1094 "%s: L2CAP connection has been terminated, so=%p, so_state=%#x, so_count=%d, " \
1095 "state=%d, flags=%#x\n", __func__, s->l2so, s->l2so->so_state,
1096 s->l2so->so_count, s->state, s->flags);
1098 s->state = NG_BTSOCKET_RFCOMM_SESSION_CLOSED;
1099 ng_btsocket_rfcomm_session_clean(s);
1102 /* Now process upcall */
1104 /* Try to accept new L2CAP connection(s) */
1105 case NG_BTSOCKET_RFCOMM_SESSION_LISTENING:
1106 while (ng_btsocket_rfcomm_session_accept(s) == 0)
1110 /* Process the results of the L2CAP connect */
1111 case NG_BTSOCKET_RFCOMM_SESSION_CONNECTING:
1112 ng_btsocket_rfcomm_session_process_pcb(s);
1114 if (ng_btsocket_rfcomm_session_connect(s) != 0) {
1115 s->state = NG_BTSOCKET_RFCOMM_SESSION_CLOSED;
1116 ng_btsocket_rfcomm_session_clean(s);
1120 /* Try to receive/send more data */
1121 case NG_BTSOCKET_RFCOMM_SESSION_CONNECTED:
1122 case NG_BTSOCKET_RFCOMM_SESSION_OPEN:
1123 case NG_BTSOCKET_RFCOMM_SESSION_DISCONNECTING:
1124 ng_btsocket_rfcomm_session_process_pcb(s);
1126 if (ng_btsocket_rfcomm_session_receive(s) != 0) {
1127 s->state = NG_BTSOCKET_RFCOMM_SESSION_CLOSED;
1128 ng_btsocket_rfcomm_session_clean(s);
1129 } else if (ng_btsocket_rfcomm_session_send(s) != 0) {
1130 s->state = NG_BTSOCKET_RFCOMM_SESSION_CLOSED;
1131 ng_btsocket_rfcomm_session_clean(s);
1135 case NG_BTSOCKET_RFCOMM_SESSION_CLOSED:
1139 panic("%s: Invalid session state=%d, flags=%#x\n",
1140 __func__, s->state, s->flags);
1143 } /* ng_btsocket_rfcomm_session_task */
1146 * Process RFCOMM connection indicator. Caller must hold s->session_mtx
1149 static ng_btsocket_rfcomm_pcb_p
1150 ng_btsocket_rfcomm_connect_ind(ng_btsocket_rfcomm_session_p s, int channel)
1152 ng_btsocket_rfcomm_pcb_p pcb = NULL, pcb1 = NULL;
1153 ng_btsocket_l2cap_pcb_p l2pcb = NULL;
1156 mtx_assert(&s->session_mtx, MA_OWNED);
1159 * Try to find RFCOMM socket that listens on given source address
1160 * and channel. This will return the best possible match.
1163 l2pcb = so2l2cap_pcb(s->l2so);
1164 pcb = ng_btsocket_rfcomm_pcb_listener(&l2pcb->src, channel);
1169 * Check the pending connections queue and if we have space then
1170 * create new socket and set proper source and destination address,
1174 mtx_lock(&pcb->pcb_mtx);
1176 CURVNET_SET(pcb->so->so_vnet);
1177 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 l2sa.l2cap_bdaddr_type = BDADDR_BREDR;
1345 error = sobind(s->l2so, (struct sockaddr *) &l2sa, td);
1349 /* If "dst" is not NULL then initiate connect(), otherwise listen() */
1352 s->state = NG_BTSOCKET_RFCOMM_SESSION_LISTENING;
1354 error = solisten(s->l2so, 10, td);
1358 s->flags = NG_BTSOCKET_RFCOMM_SESSION_INITIATOR;
1359 s->state = NG_BTSOCKET_RFCOMM_SESSION_CONNECTING;
1361 l2sa.l2cap_len = sizeof(l2sa);
1362 l2sa.l2cap_family = AF_BLUETOOTH;
1363 l2sa.l2cap_psm = htole16(NG_L2CAP_PSM_RFCOMM);
1364 bcopy(dst, &l2sa.l2cap_bdaddr, sizeof(l2sa.l2cap_bdaddr));
1366 l2sa.l2cap_bdaddr_type = BDADDR_BREDR;
1368 error = soconnect(s->l2so, (struct sockaddr *) &l2sa, td);
1374 LIST_INSERT_HEAD(&ng_btsocket_rfcomm_sessions, s, next);
1377 mtx_unlock(&s->session_mtx);
1382 mtx_unlock(&s->session_mtx);
1384 /* Return L2CAP socket back to its original state */
1385 SOCKBUF_LOCK(&l2so->so_rcv);
1386 soupcall_clear(s->l2so, SO_RCV);
1387 SOCKBUF_UNLOCK(&l2so->so_rcv);
1388 SOCKBUF_LOCK(&l2so->so_snd);
1389 soupcall_clear(s->l2so, SO_SND);
1390 SOCKBUF_UNLOCK(&l2so->so_snd);
1391 l2so->so_state &= ~SS_NBIO;
1393 mtx_destroy(&s->session_mtx);
1394 bzero(s, sizeof(*s));
1395 free(s, M_NETGRAPH_BTSOCKET_RFCOMM);
1398 } /* ng_btsocket_rfcomm_session_create */
1401 * Process accept() on RFCOMM session
1402 * XXX FIXME locking for "l2so"?
1406 ng_btsocket_rfcomm_session_accept(ng_btsocket_rfcomm_session_p s0)
1408 struct socket *l2so;
1409 struct sockaddr_l2cap *l2sa = NULL;
1410 ng_btsocket_l2cap_pcb_t *l2pcb = NULL;
1411 ng_btsocket_rfcomm_session_p s = NULL;
1414 mtx_assert(&ng_btsocket_rfcomm_sessions_mtx, MA_OWNED);
1415 mtx_assert(&s0->session_mtx, MA_OWNED);
1417 SOLISTEN_LOCK(s0->l2so);
1418 error = solisten_dequeue(s0->l2so, &l2so, 0);
1419 if (error == EWOULDBLOCK)
1422 NG_BTSOCKET_RFCOMM_ERR(
1423 "%s: Could not accept connection on L2CAP socket, error=%d\n", __func__, error);
1427 error = soaccept(l2so, (struct sockaddr **) &l2sa);
1429 NG_BTSOCKET_RFCOMM_ERR(
1430 "%s: soaccept() on L2CAP socket failed, error=%d\n", __func__, error);
1437 * Check if there is already active RFCOMM session between two devices.
1438 * If so then close L2CAP connection. We only support one RFCOMM session
1439 * between each pair of devices. Note that here we assume session in any
1440 * state. The session even could be in the middle of disconnecting.
1443 l2pcb = so2l2cap_pcb(l2so);
1444 s = ng_btsocket_rfcomm_session_by_addr(&l2pcb->src, &l2pcb->dst);
1446 /* Create a new RFCOMM session */
1447 error = ng_btsocket_rfcomm_session_create(&s, l2so, NULL, NULL,
1448 curthread /* XXX */);
1450 mtx_lock(&s->session_mtx);
1453 s->state = NG_BTSOCKET_RFCOMM_SESSION_CONNECTED;
1456 * Adjust MTU on incoming connection. Reserve 5 bytes:
1457 * RFCOMM frame header, one extra byte for length and
1458 * one extra byte for credits.
1461 s->mtu = min(l2pcb->imtu, l2pcb->omtu) -
1462 sizeof(struct rfcomm_frame_hdr) - 1 - 1;
1464 mtx_unlock(&s->session_mtx);
1466 NG_BTSOCKET_RFCOMM_ALERT(
1467 "%s: Failed to create new RFCOMM session, error=%d\n", __func__, error);
1472 NG_BTSOCKET_RFCOMM_WARN(
1473 "%s: Rejecting duplicating RFCOMM session between src=%x:%x:%x:%x:%x:%x and " \
1474 "dst=%x:%x:%x:%x:%x:%x, state=%d, flags=%#x\n", __func__,
1475 l2pcb->src.b[5], l2pcb->src.b[4], l2pcb->src.b[3],
1476 l2pcb->src.b[2], l2pcb->src.b[1], l2pcb->src.b[0],
1477 l2pcb->dst.b[5], l2pcb->dst.b[4], l2pcb->dst.b[3],
1478 l2pcb->dst.b[2], l2pcb->dst.b[1], l2pcb->dst.b[0],
1479 s->state, s->flags);
1486 } /* ng_btsocket_rfcomm_session_accept */
1489 * Process connect() on RFCOMM session
1490 * XXX FIXME locking for "l2so"?
1494 ng_btsocket_rfcomm_session_connect(ng_btsocket_rfcomm_session_p s)
1496 ng_btsocket_l2cap_pcb_p l2pcb = so2l2cap_pcb(s->l2so);
1499 mtx_assert(&s->session_mtx, MA_OWNED);
1501 /* First check if connection has failed */
1502 if ((error = s->l2so->so_error) != 0) {
1503 s->l2so->so_error = 0;
1505 NG_BTSOCKET_RFCOMM_ERR(
1506 "%s: Could not connect RFCOMM session, error=%d, state=%d, flags=%#x\n",
1507 __func__, error, s->state, s->flags);
1512 /* Is connection still in progress? */
1513 if (s->l2so->so_state & SS_ISCONNECTING)
1517 * If we got here then we are connected. Send SABM on DLCI 0 to
1518 * open multiplexor channel.
1522 s->state = NG_BTSOCKET_RFCOMM_SESSION_CONNECTED;
1525 * Adjust MTU on outgoing connection. Reserve 5 bytes: RFCOMM
1526 * frame header, one extra byte for length and one extra byte
1530 s->mtu = min(l2pcb->imtu, l2pcb->omtu) -
1531 sizeof(struct rfcomm_frame_hdr) - 1 - 1;
1533 error = ng_btsocket_rfcomm_send_command(s,RFCOMM_FRAME_SABM,0);
1535 error = ng_btsocket_rfcomm_task_wakeup();
1539 }/* ng_btsocket_rfcomm_session_connect */
1542 * Receive data on RFCOMM session
1543 * XXX FIXME locking for "l2so"?
1547 ng_btsocket_rfcomm_session_receive(ng_btsocket_rfcomm_session_p s)
1549 struct mbuf *m = NULL;
1551 int more, flags, error;
1553 mtx_assert(&s->session_mtx, MA_OWNED);
1555 /* Can we read from the L2CAP socket? */
1556 if (!soreadable(s->l2so))
1559 /* First check for error on L2CAP socket */
1560 if ((error = s->l2so->so_error) != 0) {
1561 s->l2so->so_error = 0;
1563 NG_BTSOCKET_RFCOMM_ERR(
1564 "%s: Could not receive data from L2CAP socket, error=%d, state=%d, flags=%#x\n",
1565 __func__, error, s->state, s->flags);
1571 * Read all packets from the L2CAP socket.
1572 * XXX FIXME/VERIFY is that correct? For now use m->m_nextpkt as
1573 * indication that there is more packets on the socket's buffer.
1574 * Also what should we use in uio.uio_resid?
1575 * May be s->mtu + sizeof(struct rfcomm_frame_hdr) + 1 + 1?
1578 for (more = 1; more; ) {
1579 /* Try to get next packet from socket */
1580 bzero(&uio, sizeof(uio));
1581 /* uio.uio_td = NULL; */
1582 uio.uio_resid = 1000000000;
1583 flags = MSG_DONTWAIT;
1586 error = soreceive(s->l2so, NULL, &uio, &m,
1587 (struct mbuf **) NULL, &flags);
1589 if (error == EWOULDBLOCK)
1590 return (0); /* XXX can happen? */
1592 NG_BTSOCKET_RFCOMM_ERR(
1593 "%s: Could not receive data from L2CAP socket, error=%d\n", __func__, error);
1598 more = (m->m_nextpkt != NULL);
1599 m->m_nextpkt = NULL;
1601 ng_btsocket_rfcomm_receive_frame(s, m);
1605 } /* ng_btsocket_rfcomm_session_receive */
1608 * Send data on RFCOMM session
1609 * XXX FIXME locking for "l2so"?
1613 ng_btsocket_rfcomm_session_send(ng_btsocket_rfcomm_session_p s)
1615 struct mbuf *m = NULL;
1618 mtx_assert(&s->session_mtx, MA_OWNED);
1620 /* Send as much as we can from the session queue */
1621 while (sowriteable(s->l2so)) {
1622 /* Check if socket still OK */
1623 if ((error = s->l2so->so_error) != 0) {
1624 s->l2so->so_error = 0;
1626 NG_BTSOCKET_RFCOMM_ERR(
1627 "%s: Detected error=%d on L2CAP socket, state=%d, flags=%#x\n",
1628 __func__, error, s->state, s->flags);
1633 NG_BT_MBUFQ_DEQUEUE(&s->outq, m);
1635 return (0); /* we are done */
1637 /* Call send function on the L2CAP socket */
1638 error = (*s->l2so->so_proto->pr_usrreqs->pru_send)(s->l2so,
1639 0, m, NULL, NULL, curthread /* XXX */);
1641 NG_BTSOCKET_RFCOMM_ERR(
1642 "%s: Could not send data to L2CAP socket, error=%d\n", __func__, error);
1649 } /* ng_btsocket_rfcomm_session_send */
1652 * Close and disconnect all DLCs for the given session. Caller must hold
1653 * s->sesson_mtx. Will wakeup session.
1657 ng_btsocket_rfcomm_session_clean(ng_btsocket_rfcomm_session_p s)
1659 ng_btsocket_rfcomm_pcb_p pcb = NULL, pcb_next = NULL;
1662 mtx_assert(&s->session_mtx, MA_OWNED);
1665 * Note: cannot use LIST_FOREACH because ng_btsocket_rfcomm_pcb_kill
1666 * will unlink DLC from the session
1669 for (pcb = LIST_FIRST(&s->dlcs); pcb != NULL; ) {
1670 mtx_lock(&pcb->pcb_mtx);
1671 pcb_next = LIST_NEXT(pcb, session_next);
1673 NG_BTSOCKET_RFCOMM_INFO(
1674 "%s: Disconnecting dlci=%d, state=%d, flags=%#x\n",
1675 __func__, pcb->dlci, pcb->state, pcb->flags);
1677 if (pcb->state == NG_BTSOCKET_RFCOMM_DLC_CONNECTED)
1680 error = ECONNREFUSED;
1682 ng_btsocket_rfcomm_pcb_kill(pcb, error);
1684 mtx_unlock(&pcb->pcb_mtx);
1687 } /* ng_btsocket_rfcomm_session_clean */
1690 * Process all DLCs on the session. Caller MUST hold s->session_mtx.
1694 ng_btsocket_rfcomm_session_process_pcb(ng_btsocket_rfcomm_session_p s)
1696 ng_btsocket_rfcomm_pcb_p pcb = NULL, pcb_next = NULL;
1699 mtx_assert(&s->session_mtx, MA_OWNED);
1702 * Note: cannot use LIST_FOREACH because ng_btsocket_rfcomm_pcb_kill
1703 * will unlink DLC from the session
1706 for (pcb = LIST_FIRST(&s->dlcs); pcb != NULL; ) {
1707 mtx_lock(&pcb->pcb_mtx);
1708 pcb_next = LIST_NEXT(pcb, session_next);
1710 switch (pcb->state) {
1713 * If DLC in W4_CONNECT state then we should check for both
1714 * timeout and detach.
1717 case NG_BTSOCKET_RFCOMM_DLC_W4_CONNECT:
1718 if (pcb->flags & NG_BTSOCKET_RFCOMM_DLC_DETACHED)
1719 ng_btsocket_rfcomm_pcb_kill(pcb, 0);
1720 else if (pcb->flags & NG_BTSOCKET_RFCOMM_DLC_TIMEDOUT)
1721 ng_btsocket_rfcomm_pcb_kill(pcb, ETIMEDOUT);
1725 * If DLC in CONFIGURING or CONNECTING state then we only
1726 * should check for timeout. If detach() was called then
1727 * DLC will be moved into DISCONNECTING state.
1730 case NG_BTSOCKET_RFCOMM_DLC_CONFIGURING:
1731 case NG_BTSOCKET_RFCOMM_DLC_CONNECTING:
1732 if (pcb->flags & NG_BTSOCKET_RFCOMM_DLC_TIMEDOUT)
1733 ng_btsocket_rfcomm_pcb_kill(pcb, ETIMEDOUT);
1737 * If DLC in CONNECTED state then we need to send data (if any)
1738 * from the socket's send queue. Note that we will send data
1739 * from either all sockets or none. This may overload session's
1740 * outgoing queue (but we do not check for that).
1742 * XXX FIXME need scheduler for RFCOMM sockets
1745 case NG_BTSOCKET_RFCOMM_DLC_CONNECTED:
1746 error = ng_btsocket_rfcomm_pcb_send(pcb, ALOT);
1748 ng_btsocket_rfcomm_pcb_kill(pcb, error);
1752 * If DLC in DISCONNECTING state then we must send DISC frame.
1753 * Note that if DLC has timeout set then we do not need to
1754 * resend DISC frame.
1756 * XXX FIXME need to drain all data from the socket's queue
1757 * if LINGER option was set
1760 case NG_BTSOCKET_RFCOMM_DLC_DISCONNECTING:
1761 if (!(pcb->flags & NG_BTSOCKET_RFCOMM_DLC_TIMO)) {
1762 error = ng_btsocket_rfcomm_send_command(
1763 pcb->session, RFCOMM_FRAME_DISC,
1766 ng_btsocket_rfcomm_timeout(pcb);
1768 ng_btsocket_rfcomm_pcb_kill(pcb, error);
1769 } else if (pcb->flags & NG_BTSOCKET_RFCOMM_DLC_TIMEDOUT)
1770 ng_btsocket_rfcomm_pcb_kill(pcb, ETIMEDOUT);
1773 /* case NG_BTSOCKET_RFCOMM_DLC_CLOSED: */
1775 panic("%s: Invalid DLC state=%d, flags=%#x\n",
1776 __func__, pcb->state, pcb->flags);
1780 mtx_unlock(&pcb->pcb_mtx);
1783 } /* ng_btsocket_rfcomm_session_process_pcb */
1786 * Find RFCOMM session between "src" and "dst".
1787 * Caller MUST hold ng_btsocket_rfcomm_sessions_mtx.
1790 static ng_btsocket_rfcomm_session_p
1791 ng_btsocket_rfcomm_session_by_addr(bdaddr_p src, bdaddr_p dst)
1793 ng_btsocket_rfcomm_session_p s = NULL;
1794 ng_btsocket_l2cap_pcb_p l2pcb = NULL;
1797 mtx_assert(&ng_btsocket_rfcomm_sessions_mtx, MA_OWNED);
1799 any_src = (bcmp(src, NG_HCI_BDADDR_ANY, sizeof(*src)) == 0);
1801 LIST_FOREACH(s, &ng_btsocket_rfcomm_sessions, next) {
1802 l2pcb = so2l2cap_pcb(s->l2so);
1804 if ((any_src || bcmp(&l2pcb->src, src, sizeof(*src)) == 0) &&
1805 bcmp(&l2pcb->dst, dst, sizeof(*dst)) == 0)
1810 } /* ng_btsocket_rfcomm_session_by_addr */
1812 /*****************************************************************************
1813 *****************************************************************************
1815 *****************************************************************************
1816 *****************************************************************************/
1819 * Process incoming RFCOMM frame. Caller must hold s->session_mtx.
1820 * XXX FIXME check frame length
1824 ng_btsocket_rfcomm_receive_frame(ng_btsocket_rfcomm_session_p s,
1827 struct rfcomm_frame_hdr *hdr = NULL;
1828 struct mbuf *m = NULL;
1830 u_int8_t dlci, type;
1833 mtx_assert(&s->session_mtx, MA_OWNED);
1835 /* Pullup as much as we can into first mbuf (for direct access) */
1836 length = min(m0->m_pkthdr.len, MHLEN);
1837 if (m0->m_len < length) {
1838 if ((m0 = m_pullup(m0, length)) == NULL) {
1839 NG_BTSOCKET_RFCOMM_ALERT(
1840 "%s: m_pullup(%d) failed\n", __func__, length);
1846 hdr = mtod(m0, struct rfcomm_frame_hdr *);
1847 dlci = RFCOMM_DLCI(hdr->address);
1848 type = RFCOMM_TYPE(hdr->control);
1850 /* Test EA bit in length. If not set then we have 2 bytes of length */
1851 if (!RFCOMM_EA(hdr->length)) {
1852 bcopy(&hdr->length, &length, sizeof(length));
1853 length = le16toh(length) >> 1;
1854 m_adj(m0, sizeof(*hdr) + 1);
1856 length = hdr->length >> 1;
1857 m_adj(m0, sizeof(*hdr));
1860 NG_BTSOCKET_RFCOMM_INFO(
1861 "%s: Got frame type=%#x, dlci=%d, length=%d, cr=%d, pf=%d, len=%d\n",
1862 __func__, type, dlci, length, RFCOMM_CR(hdr->address),
1863 RFCOMM_PF(hdr->control), m0->m_pkthdr.len);
1866 * Get FCS (the last byte in the frame)
1867 * XXX this will not work if mbuf chain ends with empty mbuf.
1868 * XXX let's hope it never happens :)
1871 for (m = m0; m->m_next != NULL; m = m->m_next)
1874 panic("%s: Empty mbuf at the end of the chain, len=%d\n",
1875 __func__, m->m_len);
1878 * Check FCS. We only need to calculate FCS on first 2 or 3 bytes
1879 * and already m_pullup'ed mbuf chain, so it should be safe.
1882 if (ng_btsocket_rfcomm_check_fcs((u_int8_t *) hdr, type, m->m_data[m->m_len - 1])) {
1883 NG_BTSOCKET_RFCOMM_ERR(
1884 "%s: Invalid RFCOMM packet. Bad checksum\n", __func__);
1890 m_adj(m0, -1); /* Trim FCS byte */
1893 * Process RFCOMM frame.
1895 * From TS 07.10 spec
1897 * "... In the case where a SABM or DISC command with the P bit set
1898 * to 0 is received then the received frame shall be discarded..."
1900 * "... If a unsolicited DM response is received then the frame shall
1901 * be processed irrespective of the P/F setting... "
1903 * "... The station may transmit response frames with the F bit set
1904 * to 0 at any opportunity on an asynchronous basis. However, in the
1905 * case where a UA response is received with the F bit set to 0 then
1906 * the received frame shall be discarded..."
1908 * From Bluetooth spec
1910 * "... When credit based flow control is being used, the meaning of
1911 * the P/F bit in the control field of the RFCOMM header is redefined
1912 * for UIH frames..."
1916 case RFCOMM_FRAME_SABM:
1917 if (RFCOMM_PF(hdr->control))
1918 error = ng_btsocket_rfcomm_receive_sabm(s, dlci);
1921 case RFCOMM_FRAME_DISC:
1922 if (RFCOMM_PF(hdr->control))
1923 error = ng_btsocket_rfcomm_receive_disc(s, dlci);
1926 case RFCOMM_FRAME_UA:
1927 if (RFCOMM_PF(hdr->control))
1928 error = ng_btsocket_rfcomm_receive_ua(s, dlci);
1931 case RFCOMM_FRAME_DM:
1932 error = ng_btsocket_rfcomm_receive_dm(s, dlci);
1935 case RFCOMM_FRAME_UIH:
1937 error = ng_btsocket_rfcomm_receive_mcc(s, m0);
1939 error = ng_btsocket_rfcomm_receive_uih(s, dlci,
1940 RFCOMM_PF(hdr->control), m0);
1946 NG_BTSOCKET_RFCOMM_ERR(
1947 "%s: Invalid RFCOMM packet. Unknown type=%#x\n", __func__, type);
1955 } /* ng_btsocket_rfcomm_receive_frame */
1958 * Process RFCOMM SABM frame
1962 ng_btsocket_rfcomm_receive_sabm(ng_btsocket_rfcomm_session_p s, int dlci)
1964 ng_btsocket_rfcomm_pcb_p pcb = NULL;
1967 mtx_assert(&s->session_mtx, MA_OWNED);
1969 NG_BTSOCKET_RFCOMM_INFO(
1970 "%s: Got SABM, session state=%d, flags=%#x, mtu=%d, dlci=%d\n",
1971 __func__, s->state, s->flags, s->mtu, dlci);
1973 /* DLCI == 0 means open multiplexor channel */
1976 case NG_BTSOCKET_RFCOMM_SESSION_CONNECTED:
1977 case NG_BTSOCKET_RFCOMM_SESSION_OPEN:
1978 error = ng_btsocket_rfcomm_send_command(s,
1979 RFCOMM_FRAME_UA, dlci);
1981 s->state = NG_BTSOCKET_RFCOMM_SESSION_OPEN;
1982 ng_btsocket_rfcomm_connect_cfm(s);
1984 s->state = NG_BTSOCKET_RFCOMM_SESSION_CLOSED;
1985 ng_btsocket_rfcomm_session_clean(s);
1990 NG_BTSOCKET_RFCOMM_WARN(
1991 "%s: Got SABM for session in invalid state state=%d, flags=%#x\n",
1992 __func__, s->state, s->flags);
2000 /* Make sure multiplexor channel is open */
2001 if (s->state != NG_BTSOCKET_RFCOMM_SESSION_OPEN) {
2002 NG_BTSOCKET_RFCOMM_ERR(
2003 "%s: Got SABM for dlci=%d with mulitplexor channel closed, state=%d, " \
2004 "flags=%#x\n", __func__, dlci, s->state, s->flags);
2010 * Check if we have this DLCI. This might happen when remote
2011 * peer uses PN command before actual open (SABM) happens.
2014 pcb = ng_btsocket_rfcomm_pcb_by_dlci(s, dlci);
2016 mtx_lock(&pcb->pcb_mtx);
2018 if (pcb->state != NG_BTSOCKET_RFCOMM_DLC_CONNECTING) {
2019 NG_BTSOCKET_RFCOMM_ERR(
2020 "%s: Got SABM for dlci=%d in invalid state=%d, flags=%#x\n",
2021 __func__, dlci, pcb->state, pcb->flags);
2022 mtx_unlock(&pcb->pcb_mtx);
2027 ng_btsocket_rfcomm_untimeout(pcb);
2029 error = ng_btsocket_rfcomm_send_command(s,RFCOMM_FRAME_UA,dlci);
2031 error = ng_btsocket_rfcomm_send_msc(pcb);
2034 pcb->state = NG_BTSOCKET_RFCOMM_DLC_CONNECTED;
2035 soisconnected(pcb->so);
2037 ng_btsocket_rfcomm_pcb_kill(pcb, error);
2039 mtx_unlock(&pcb->pcb_mtx);
2045 * We do not have requested DLCI, so it must be an incoming connection
2046 * with default parameters. Try to accept it.
2049 pcb = ng_btsocket_rfcomm_connect_ind(s, RFCOMM_SRVCHANNEL(dlci));
2051 mtx_lock(&pcb->pcb_mtx);
2055 error = ng_btsocket_rfcomm_send_command(s,RFCOMM_FRAME_UA,dlci);
2057 error = ng_btsocket_rfcomm_send_msc(pcb);
2060 pcb->state = NG_BTSOCKET_RFCOMM_DLC_CONNECTED;
2061 soisconnected(pcb->so);
2063 ng_btsocket_rfcomm_pcb_kill(pcb, error);
2065 mtx_unlock(&pcb->pcb_mtx);
2067 /* Nobody is listen()ing on the requested DLCI */
2068 error = ng_btsocket_rfcomm_send_command(s,RFCOMM_FRAME_DM,dlci);
2071 } /* ng_btsocket_rfcomm_receive_sabm */
2074 * Process RFCOMM DISC frame
2078 ng_btsocket_rfcomm_receive_disc(ng_btsocket_rfcomm_session_p s, int dlci)
2080 ng_btsocket_rfcomm_pcb_p pcb = NULL;
2083 mtx_assert(&s->session_mtx, MA_OWNED);
2085 NG_BTSOCKET_RFCOMM_INFO(
2086 "%s: Got DISC, session state=%d, flags=%#x, mtu=%d, dlci=%d\n",
2087 __func__, s->state, s->flags, s->mtu, dlci);
2089 /* DLCI == 0 means close multiplexor channel */
2091 /* XXX FIXME assume that remote side will close the socket */
2092 error = ng_btsocket_rfcomm_send_command(s, RFCOMM_FRAME_UA, 0);
2094 if (s->state == NG_BTSOCKET_RFCOMM_SESSION_DISCONNECTING)
2095 s->state = NG_BTSOCKET_RFCOMM_SESSION_CLOSED; /* XXX */
2097 s->state = NG_BTSOCKET_RFCOMM_SESSION_DISCONNECTING;
2099 s->state = NG_BTSOCKET_RFCOMM_SESSION_CLOSED; /* XXX */
2101 ng_btsocket_rfcomm_session_clean(s);
2103 pcb = ng_btsocket_rfcomm_pcb_by_dlci(s, dlci);
2107 mtx_lock(&pcb->pcb_mtx);
2109 NG_BTSOCKET_RFCOMM_INFO(
2110 "%s: Got DISC for dlci=%d, state=%d, flags=%#x\n",
2111 __func__, dlci, pcb->state, pcb->flags);
2113 error = ng_btsocket_rfcomm_send_command(s,
2114 RFCOMM_FRAME_UA, dlci);
2116 if (pcb->state == NG_BTSOCKET_RFCOMM_DLC_CONNECTED)
2121 ng_btsocket_rfcomm_pcb_kill(pcb, err);
2123 mtx_unlock(&pcb->pcb_mtx);
2125 NG_BTSOCKET_RFCOMM_WARN(
2126 "%s: Got DISC for non-existing dlci=%d\n", __func__, dlci);
2128 error = ng_btsocket_rfcomm_send_command(s,
2129 RFCOMM_FRAME_DM, dlci);
2134 } /* ng_btsocket_rfcomm_receive_disc */
2137 * Process RFCOMM UA frame
2141 ng_btsocket_rfcomm_receive_ua(ng_btsocket_rfcomm_session_p s, int dlci)
2143 ng_btsocket_rfcomm_pcb_p pcb = NULL;
2146 mtx_assert(&s->session_mtx, MA_OWNED);
2148 NG_BTSOCKET_RFCOMM_INFO(
2149 "%s: Got UA, session state=%d, flags=%#x, mtu=%d, dlci=%d\n",
2150 __func__, s->state, s->flags, s->mtu, dlci);
2152 /* dlci == 0 means multiplexor channel */
2155 case NG_BTSOCKET_RFCOMM_SESSION_CONNECTED:
2156 s->state = NG_BTSOCKET_RFCOMM_SESSION_OPEN;
2157 ng_btsocket_rfcomm_connect_cfm(s);
2160 case NG_BTSOCKET_RFCOMM_SESSION_DISCONNECTING:
2161 s->state = NG_BTSOCKET_RFCOMM_SESSION_CLOSED;
2162 ng_btsocket_rfcomm_session_clean(s);
2166 NG_BTSOCKET_RFCOMM_WARN(
2167 "%s: Got UA for session in invalid state=%d(%d), flags=%#x, mtu=%d\n",
2168 __func__, s->state, INITIATOR(s), s->flags,
2177 /* Check if we have this DLCI */
2178 pcb = ng_btsocket_rfcomm_pcb_by_dlci(s, dlci);
2180 mtx_lock(&pcb->pcb_mtx);
2182 NG_BTSOCKET_RFCOMM_INFO(
2183 "%s: Got UA for dlci=%d, state=%d, flags=%#x\n",
2184 __func__, dlci, pcb->state, pcb->flags);
2186 switch (pcb->state) {
2187 case NG_BTSOCKET_RFCOMM_DLC_CONNECTING:
2188 ng_btsocket_rfcomm_untimeout(pcb);
2190 error = ng_btsocket_rfcomm_send_msc(pcb);
2192 pcb->state = NG_BTSOCKET_RFCOMM_DLC_CONNECTED;
2193 soisconnected(pcb->so);
2197 case NG_BTSOCKET_RFCOMM_DLC_DISCONNECTING:
2198 ng_btsocket_rfcomm_pcb_kill(pcb, 0);
2202 NG_BTSOCKET_RFCOMM_WARN(
2203 "%s: Got UA for dlci=%d in invalid state=%d, flags=%#x\n",
2204 __func__, dlci, pcb->state, pcb->flags);
2209 mtx_unlock(&pcb->pcb_mtx);
2211 NG_BTSOCKET_RFCOMM_WARN(
2212 "%s: Got UA for non-existing dlci=%d\n", __func__, dlci);
2214 error = ng_btsocket_rfcomm_send_command(s,RFCOMM_FRAME_DM,dlci);
2218 } /* ng_btsocket_rfcomm_receive_ua */
2221 * Process RFCOMM DM frame
2225 ng_btsocket_rfcomm_receive_dm(ng_btsocket_rfcomm_session_p s, int dlci)
2227 ng_btsocket_rfcomm_pcb_p pcb = NULL;
2230 mtx_assert(&s->session_mtx, MA_OWNED);
2232 NG_BTSOCKET_RFCOMM_INFO(
2233 "%s: Got DM, session state=%d, flags=%#x, mtu=%d, dlci=%d\n",
2234 __func__, s->state, s->flags, s->mtu, dlci);
2236 /* DLCI == 0 means multiplexor channel */
2238 /* Disconnect all dlc's on the session */
2239 s->state = NG_BTSOCKET_RFCOMM_SESSION_CLOSED;
2240 ng_btsocket_rfcomm_session_clean(s);
2242 pcb = ng_btsocket_rfcomm_pcb_by_dlci(s, dlci);
2244 mtx_lock(&pcb->pcb_mtx);
2246 NG_BTSOCKET_RFCOMM_INFO(
2247 "%s: Got DM for dlci=%d, state=%d, flags=%#x\n",
2248 __func__, dlci, pcb->state, pcb->flags);
2250 if (pcb->state == NG_BTSOCKET_RFCOMM_DLC_CONNECTED)
2253 error = ECONNREFUSED;
2255 ng_btsocket_rfcomm_pcb_kill(pcb, error);
2257 mtx_unlock(&pcb->pcb_mtx);
2259 NG_BTSOCKET_RFCOMM_WARN(
2260 "%s: Got DM for non-existing dlci=%d\n", __func__, dlci);
2264 } /* ng_btsocket_rfcomm_receive_dm */
2267 * Process RFCOMM UIH frame (data)
2271 ng_btsocket_rfcomm_receive_uih(ng_btsocket_rfcomm_session_p s, int dlci,
2272 int pf, struct mbuf *m0)
2274 ng_btsocket_rfcomm_pcb_p pcb = NULL;
2277 mtx_assert(&s->session_mtx, MA_OWNED);
2279 NG_BTSOCKET_RFCOMM_INFO(
2280 "%s: Got UIH, session state=%d, flags=%#x, mtu=%d, dlci=%d, pf=%d, len=%d\n",
2281 __func__, s->state, s->flags, s->mtu, dlci, pf,
2284 /* XXX should we do it here? Check for session flow control */
2285 if (s->flags & NG_BTSOCKET_RFCOMM_SESSION_LFC) {
2286 NG_BTSOCKET_RFCOMM_WARN(
2287 "%s: Got UIH with session flow control asserted, state=%d, flags=%#x\n",
2288 __func__, s->state, s->flags);
2292 /* Check if we have this dlci */
2293 pcb = ng_btsocket_rfcomm_pcb_by_dlci(s, dlci);
2295 NG_BTSOCKET_RFCOMM_WARN(
2296 "%s: Got UIH for non-existing dlci=%d\n", __func__, dlci);
2297 error = ng_btsocket_rfcomm_send_command(s,RFCOMM_FRAME_DM,dlci);
2301 mtx_lock(&pcb->pcb_mtx);
2303 /* Check dlci state */
2304 if (pcb->state != NG_BTSOCKET_RFCOMM_DLC_CONNECTED) {
2305 NG_BTSOCKET_RFCOMM_WARN(
2306 "%s: Got UIH for dlci=%d in invalid state=%d, flags=%#x\n",
2307 __func__, dlci, pcb->state, pcb->flags);
2312 /* Check dlci flow control */
2313 if (((pcb->flags & NG_BTSOCKET_RFCOMM_DLC_CFC) && pcb->rx_cred <= 0) ||
2314 (pcb->lmodem & RFCOMM_MODEM_FC)) {
2315 NG_BTSOCKET_RFCOMM_ERR(
2316 "%s: Got UIH for dlci=%d with asserted flow control, state=%d, " \
2317 "flags=%#x, rx_cred=%d, lmodem=%#x\n",
2318 __func__, dlci, pcb->state, pcb->flags,
2319 pcb->rx_cred, pcb->lmodem);
2323 /* Did we get any credits? */
2324 if ((pcb->flags & NG_BTSOCKET_RFCOMM_DLC_CFC) && pf) {
2325 NG_BTSOCKET_RFCOMM_INFO(
2326 "%s: Got %d more credits for dlci=%d, state=%d, flags=%#x, " \
2327 "rx_cred=%d, tx_cred=%d\n",
2328 __func__, *mtod(m0, u_int8_t *), dlci, pcb->state,
2329 pcb->flags, pcb->rx_cred, pcb->tx_cred);
2331 pcb->tx_cred += *mtod(m0, u_int8_t *);
2334 /* Send more from the DLC. XXX check for errors? */
2335 ng_btsocket_rfcomm_pcb_send(pcb, ALOT);
2338 /* OK the of the rest of the mbuf is the data */
2339 if (m0->m_pkthdr.len > 0) {
2340 /* If we are using credit flow control decrease rx_cred here */
2341 if (pcb->flags & NG_BTSOCKET_RFCOMM_DLC_CFC) {
2342 /* Give remote peer more credits (if needed) */
2343 if (-- pcb->rx_cred <= RFCOMM_MAX_CREDITS / 2)
2344 ng_btsocket_rfcomm_send_credits(pcb);
2346 NG_BTSOCKET_RFCOMM_INFO(
2347 "%s: Remote side still has credits, dlci=%d, state=%d, flags=%#x, " \
2348 "rx_cred=%d, tx_cred=%d\n", __func__, dlci, pcb->state, pcb->flags,
2349 pcb->rx_cred, pcb->tx_cred);
2352 /* Check packet against mtu on dlci */
2353 if (m0->m_pkthdr.len > pcb->mtu) {
2354 NG_BTSOCKET_RFCOMM_ERR(
2355 "%s: Got oversized UIH for dlci=%d, state=%d, flags=%#x, mtu=%d, len=%d\n",
2356 __func__, dlci, pcb->state, pcb->flags,
2357 pcb->mtu, m0->m_pkthdr.len);
2360 } else if (m0->m_pkthdr.len > sbspace(&pcb->so->so_rcv)) {
2363 * This is really bad. Receive queue on socket does
2364 * not have enough space for the packet. We do not
2365 * have any other choice but drop the packet.
2368 NG_BTSOCKET_RFCOMM_ERR(
2369 "%s: Not enough space in socket receive queue. Dropping UIH for dlci=%d, " \
2370 "state=%d, flags=%#x, len=%d, space=%ld\n",
2371 __func__, dlci, pcb->state, pcb->flags,
2372 m0->m_pkthdr.len, sbspace(&pcb->so->so_rcv));
2376 /* Append packet to the socket receive queue */
2377 sbappend(&pcb->so->so_rcv, m0, 0);
2384 mtx_unlock(&pcb->pcb_mtx);
2386 NG_FREE_M(m0); /* checks for != NULL */
2389 } /* ng_btsocket_rfcomm_receive_uih */
2392 * Process RFCOMM MCC command (Multiplexor)
2394 * From TS 07.10 spec
2396 * "5.4.3.1 Information Data
2398 * ...The frames (UIH) sent by the initiating station have the C/R bit set
2399 * to 1 and those sent by the responding station have the C/R bit set to 0..."
2401 * "5.4.6.2 Operating procedures
2403 * Messages always exist in pairs; a command message and a corresponding
2404 * response message. If the C/R bit is set to 1 the message is a command,
2405 * if it is set to 0 the message is a response...
2409 * NOTE: Notice that when UIH frames are used to convey information on DLCI 0
2410 * there are at least two different fields that contain a C/R bit, and the
2411 * bits are set of different form. The C/R bit in the Type field shall be set
2412 * as it is stated above, while the C/R bit in the Address field (see subclause
2413 * 5.2.1.2) shall be set as it is described in subclause 5.4.3.1."
2417 ng_btsocket_rfcomm_receive_mcc(ng_btsocket_rfcomm_session_p s, struct mbuf *m0)
2419 struct rfcomm_mcc_hdr *hdr = NULL;
2420 u_int8_t cr, type, length;
2422 mtx_assert(&s->session_mtx, MA_OWNED);
2425 * We can access data directly in the first mbuf, because we have
2426 * m_pullup()'ed mbuf chain in ng_btsocket_rfcomm_receive_frame().
2427 * All MCC commands should fit into single mbuf (except probably TEST).
2430 hdr = mtod(m0, struct rfcomm_mcc_hdr *);
2431 cr = RFCOMM_CR(hdr->type);
2432 type = RFCOMM_MCC_TYPE(hdr->type);
2433 length = RFCOMM_MCC_LENGTH(hdr->length);
2435 /* Check MCC frame length */
2436 if (sizeof(*hdr) + length != m0->m_pkthdr.len) {
2437 NG_BTSOCKET_RFCOMM_ERR(
2438 "%s: Invalid MCC frame length=%d, len=%d\n",
2439 __func__, length, m0->m_pkthdr.len);
2446 case RFCOMM_MCC_TEST:
2447 return (ng_btsocket_rfcomm_receive_test(s, m0));
2450 case RFCOMM_MCC_FCON:
2451 case RFCOMM_MCC_FCOFF:
2452 return (ng_btsocket_rfcomm_receive_fc(s, m0));
2455 case RFCOMM_MCC_MSC:
2456 return (ng_btsocket_rfcomm_receive_msc(s, m0));
2459 case RFCOMM_MCC_RPN:
2460 return (ng_btsocket_rfcomm_receive_rpn(s, m0));
2463 case RFCOMM_MCC_RLS:
2464 return (ng_btsocket_rfcomm_receive_rls(s, m0));
2468 return (ng_btsocket_rfcomm_receive_pn(s, m0));
2471 case RFCOMM_MCC_NSC:
2472 NG_BTSOCKET_RFCOMM_ERR(
2473 "%s: Got MCC NSC, type=%#x, cr=%d, length=%d, session state=%d, flags=%#x, " \
2474 "mtu=%d, len=%d\n", __func__, RFCOMM_MCC_TYPE(*((u_int8_t *)(hdr + 1))), cr,
2475 length, s->state, s->flags, s->mtu, m0->m_pkthdr.len);
2480 NG_BTSOCKET_RFCOMM_ERR(
2481 "%s: Got unknown MCC, type=%#x, cr=%d, length=%d, session state=%d, " \
2482 "flags=%#x, mtu=%d, len=%d\n",
2483 __func__, type, cr, length, s->state, s->flags,
2484 s->mtu, m0->m_pkthdr.len);
2486 /* Reuse mbuf to send NSC */
2487 hdr = mtod(m0, struct rfcomm_mcc_hdr *);
2488 m0->m_pkthdr.len = m0->m_len = sizeof(*hdr);
2490 /* Create MCC NSC header */
2491 hdr->type = RFCOMM_MKMCC_TYPE(0, RFCOMM_MCC_NSC);
2492 hdr->length = RFCOMM_MKLEN8(1);
2494 /* Put back MCC command type we did not like */
2495 m0->m_data[m0->m_len] = RFCOMM_MKMCC_TYPE(cr, type);
2496 m0->m_pkthdr.len ++;
2499 /* Send UIH frame */
2500 return (ng_btsocket_rfcomm_send_uih(s,
2501 RFCOMM_MKADDRESS(INITIATOR(s), 0), 0, 0, m0));
2506 } /* ng_btsocket_rfcomm_receive_mcc */
2509 * Receive RFCOMM TEST MCC command
2513 ng_btsocket_rfcomm_receive_test(ng_btsocket_rfcomm_session_p s, struct mbuf *m0)
2515 struct rfcomm_mcc_hdr *hdr = mtod(m0, struct rfcomm_mcc_hdr *);
2518 mtx_assert(&s->session_mtx, MA_OWNED);
2520 NG_BTSOCKET_RFCOMM_INFO(
2521 "%s: Got MCC TEST, cr=%d, length=%d, session state=%d, flags=%#x, mtu=%d, " \
2522 "len=%d\n", __func__, RFCOMM_CR(hdr->type), RFCOMM_MCC_LENGTH(hdr->length),
2523 s->state, s->flags, s->mtu, m0->m_pkthdr.len);
2525 if (RFCOMM_CR(hdr->type)) {
2526 hdr->type = RFCOMM_MKMCC_TYPE(0, RFCOMM_MCC_TEST);
2527 error = ng_btsocket_rfcomm_send_uih(s,
2528 RFCOMM_MKADDRESS(INITIATOR(s), 0), 0, 0, m0);
2530 NG_FREE_M(m0); /* XXX ignore response */
2533 } /* ng_btsocket_rfcomm_receive_test */
2536 * Receive RFCOMM FCON/FCOFF MCC command
2540 ng_btsocket_rfcomm_receive_fc(ng_btsocket_rfcomm_session_p s, struct mbuf *m0)
2542 struct rfcomm_mcc_hdr *hdr = mtod(m0, struct rfcomm_mcc_hdr *);
2543 u_int8_t type = RFCOMM_MCC_TYPE(hdr->type);
2546 mtx_assert(&s->session_mtx, MA_OWNED);
2549 * Turn ON/OFF aggregate flow on the entire session. When remote peer
2550 * asserted flow control no transmission shall occur except on dlci 0
2551 * (control channel).
2554 NG_BTSOCKET_RFCOMM_INFO(
2555 "%s: Got MCC FC%s, cr=%d, length=%d, session state=%d, flags=%#x, mtu=%d, " \
2556 "len=%d\n", __func__, (type == RFCOMM_MCC_FCON)? "ON" : "OFF",
2557 RFCOMM_CR(hdr->type), RFCOMM_MCC_LENGTH(hdr->length),
2558 s->state, s->flags, s->mtu, m0->m_pkthdr.len);
2560 if (RFCOMM_CR(hdr->type)) {
2561 if (type == RFCOMM_MCC_FCON)
2562 s->flags &= ~NG_BTSOCKET_RFCOMM_SESSION_RFC;
2564 s->flags |= NG_BTSOCKET_RFCOMM_SESSION_RFC;
2566 hdr->type = RFCOMM_MKMCC_TYPE(0, type);
2567 error = ng_btsocket_rfcomm_send_uih(s,
2568 RFCOMM_MKADDRESS(INITIATOR(s), 0), 0, 0, m0);
2570 NG_FREE_M(m0); /* XXX ignore response */
2573 } /* ng_btsocket_rfcomm_receive_fc */
2576 * Receive RFCOMM MSC MCC command
2580 ng_btsocket_rfcomm_receive_msc(ng_btsocket_rfcomm_session_p s, struct mbuf *m0)
2582 struct rfcomm_mcc_hdr *hdr = mtod(m0, struct rfcomm_mcc_hdr*);
2583 struct rfcomm_mcc_msc *msc = (struct rfcomm_mcc_msc *)(hdr+1);
2584 ng_btsocket_rfcomm_pcb_t *pcb = NULL;
2587 mtx_assert(&s->session_mtx, MA_OWNED);
2589 NG_BTSOCKET_RFCOMM_INFO(
2590 "%s: Got MCC MSC, dlci=%d, cr=%d, length=%d, session state=%d, flags=%#x, " \
2592 __func__, RFCOMM_DLCI(msc->address), RFCOMM_CR(hdr->type),
2593 RFCOMM_MCC_LENGTH(hdr->length), s->state, s->flags,
2594 s->mtu, m0->m_pkthdr.len);
2596 if (RFCOMM_CR(hdr->type)) {
2597 pcb = ng_btsocket_rfcomm_pcb_by_dlci(s, RFCOMM_DLCI(msc->address));
2599 NG_BTSOCKET_RFCOMM_WARN(
2600 "%s: Got MSC command for non-existing dlci=%d\n",
2601 __func__, RFCOMM_DLCI(msc->address));
2607 mtx_lock(&pcb->pcb_mtx);
2609 if (pcb->state != NG_BTSOCKET_RFCOMM_DLC_CONNECTING &&
2610 pcb->state != NG_BTSOCKET_RFCOMM_DLC_CONNECTED) {
2611 NG_BTSOCKET_RFCOMM_WARN(
2612 "%s: Got MSC on dlci=%d in invalid state=%d\n",
2613 __func__, RFCOMM_DLCI(msc->address),
2616 mtx_unlock(&pcb->pcb_mtx);
2622 pcb->rmodem = msc->modem; /* Update remote port signals */
2624 hdr->type = RFCOMM_MKMCC_TYPE(0, RFCOMM_MCC_MSC);
2625 error = ng_btsocket_rfcomm_send_uih(s,
2626 RFCOMM_MKADDRESS(INITIATOR(s), 0), 0, 0, m0);
2629 /* Send more data from DLC. XXX check for errors? */
2630 if (!(pcb->rmodem & RFCOMM_MODEM_FC) &&
2631 !(pcb->flags & NG_BTSOCKET_RFCOMM_DLC_CFC))
2632 ng_btsocket_rfcomm_pcb_send(pcb, ALOT);
2635 mtx_unlock(&pcb->pcb_mtx);
2637 NG_FREE_M(m0); /* XXX ignore response */
2640 } /* ng_btsocket_rfcomm_receive_msc */
2643 * Receive RFCOMM RPN MCC command
2644 * XXX FIXME do we need htole16/le16toh for RPN param_mask?
2648 ng_btsocket_rfcomm_receive_rpn(ng_btsocket_rfcomm_session_p s, struct mbuf *m0)
2650 struct rfcomm_mcc_hdr *hdr = mtod(m0, struct rfcomm_mcc_hdr *);
2651 struct rfcomm_mcc_rpn *rpn = (struct rfcomm_mcc_rpn *)(hdr + 1);
2653 u_int16_t param_mask;
2654 u_int8_t bit_rate, data_bits, stop_bits, parity,
2655 flow_control, xon_char, xoff_char;
2657 mtx_assert(&s->session_mtx, MA_OWNED);
2659 NG_BTSOCKET_RFCOMM_INFO(
2660 "%s: Got MCC RPN, dlci=%d, cr=%d, length=%d, session state=%d, flags=%#x, " \
2662 __func__, RFCOMM_DLCI(rpn->dlci), RFCOMM_CR(hdr->type),
2663 RFCOMM_MCC_LENGTH(hdr->length), s->state, s->flags,
2664 s->mtu, m0->m_pkthdr.len);
2666 if (RFCOMM_CR(hdr->type)) {
2667 param_mask = RFCOMM_RPN_PM_ALL;
2669 if (RFCOMM_MCC_LENGTH(hdr->length) == 1) {
2670 /* Request - return default setting */
2671 bit_rate = RFCOMM_RPN_BR_115200;
2672 data_bits = RFCOMM_RPN_DATA_8;
2673 stop_bits = RFCOMM_RPN_STOP_1;
2674 parity = RFCOMM_RPN_PARITY_NONE;
2675 flow_control = RFCOMM_RPN_FLOW_NONE;
2676 xon_char = RFCOMM_RPN_XON_CHAR;
2677 xoff_char = RFCOMM_RPN_XOFF_CHAR;
2680 * Ignore/accept bit_rate, 8 bits, 1 stop bit, no
2681 * parity, no flow control lines, default XON/XOFF
2685 bit_rate = rpn->bit_rate;
2686 rpn->param_mask = le16toh(rpn->param_mask); /* XXX */
2688 data_bits = RFCOMM_RPN_DATA_BITS(rpn->line_settings);
2689 if (rpn->param_mask & RFCOMM_RPN_PM_DATA &&
2690 data_bits != RFCOMM_RPN_DATA_8) {
2691 data_bits = RFCOMM_RPN_DATA_8;
2692 param_mask ^= RFCOMM_RPN_PM_DATA;
2695 stop_bits = RFCOMM_RPN_STOP_BITS(rpn->line_settings);
2696 if (rpn->param_mask & RFCOMM_RPN_PM_STOP &&
2697 stop_bits != RFCOMM_RPN_STOP_1) {
2698 stop_bits = RFCOMM_RPN_STOP_1;
2699 param_mask ^= RFCOMM_RPN_PM_STOP;
2702 parity = RFCOMM_RPN_PARITY(rpn->line_settings);
2703 if (rpn->param_mask & RFCOMM_RPN_PM_PARITY &&
2704 parity != RFCOMM_RPN_PARITY_NONE) {
2705 parity = RFCOMM_RPN_PARITY_NONE;
2706 param_mask ^= RFCOMM_RPN_PM_PARITY;
2709 flow_control = rpn->flow_control;
2710 if (rpn->param_mask & RFCOMM_RPN_PM_FLOW &&
2711 flow_control != RFCOMM_RPN_FLOW_NONE) {
2712 flow_control = RFCOMM_RPN_FLOW_NONE;
2713 param_mask ^= RFCOMM_RPN_PM_FLOW;
2716 xon_char = rpn->xon_char;
2717 if (rpn->param_mask & RFCOMM_RPN_PM_XON &&
2718 xon_char != RFCOMM_RPN_XON_CHAR) {
2719 xon_char = RFCOMM_RPN_XON_CHAR;
2720 param_mask ^= RFCOMM_RPN_PM_XON;
2723 xoff_char = rpn->xoff_char;
2724 if (rpn->param_mask & RFCOMM_RPN_PM_XOFF &&
2725 xoff_char != RFCOMM_RPN_XOFF_CHAR) {
2726 xoff_char = RFCOMM_RPN_XOFF_CHAR;
2727 param_mask ^= RFCOMM_RPN_PM_XOFF;
2731 rpn->bit_rate = bit_rate;
2732 rpn->line_settings = RFCOMM_MKRPN_LINE_SETTINGS(data_bits,
2734 rpn->flow_control = flow_control;
2735 rpn->xon_char = xon_char;
2736 rpn->xoff_char = xoff_char;
2737 rpn->param_mask = htole16(param_mask); /* XXX */
2739 m0->m_pkthdr.len = m0->m_len = sizeof(*hdr) + sizeof(*rpn);
2741 hdr->type = RFCOMM_MKMCC_TYPE(0, RFCOMM_MCC_RPN);
2742 error = ng_btsocket_rfcomm_send_uih(s,
2743 RFCOMM_MKADDRESS(INITIATOR(s), 0), 0, 0, m0);
2745 NG_FREE_M(m0); /* XXX ignore response */
2748 } /* ng_btsocket_rfcomm_receive_rpn */
2751 * Receive RFCOMM RLS MCC command
2755 ng_btsocket_rfcomm_receive_rls(ng_btsocket_rfcomm_session_p s, struct mbuf *m0)
2757 struct rfcomm_mcc_hdr *hdr = mtod(m0, struct rfcomm_mcc_hdr *);
2758 struct rfcomm_mcc_rls *rls = (struct rfcomm_mcc_rls *)(hdr + 1);
2761 mtx_assert(&s->session_mtx, MA_OWNED);
2764 * XXX FIXME Do we have to do anything else here? Remote peer tries to
2765 * tell us something about DLCI. Just report what we have received and
2766 * return back received values as required by TS 07.10 spec.
2769 NG_BTSOCKET_RFCOMM_INFO(
2770 "%s: Got MCC RLS, dlci=%d, status=%#x, cr=%d, length=%d, session state=%d, " \
2771 "flags=%#x, mtu=%d, len=%d\n",
2772 __func__, RFCOMM_DLCI(rls->address), rls->status,
2773 RFCOMM_CR(hdr->type), RFCOMM_MCC_LENGTH(hdr->length),
2774 s->state, s->flags, s->mtu, m0->m_pkthdr.len);
2776 if (RFCOMM_CR(hdr->type)) {
2777 if (rls->status & 0x1)
2778 NG_BTSOCKET_RFCOMM_ERR(
2779 "%s: Got RLS dlci=%d, error=%#x\n", __func__, RFCOMM_DLCI(rls->address),
2782 hdr->type = RFCOMM_MKMCC_TYPE(0, RFCOMM_MCC_RLS);
2783 error = ng_btsocket_rfcomm_send_uih(s,
2784 RFCOMM_MKADDRESS(INITIATOR(s), 0), 0, 0, m0);
2786 NG_FREE_M(m0); /* XXX ignore responses */
2789 } /* ng_btsocket_rfcomm_receive_rls */
2792 * Receive RFCOMM PN MCC command
2796 ng_btsocket_rfcomm_receive_pn(ng_btsocket_rfcomm_session_p s, struct mbuf *m0)
2798 struct rfcomm_mcc_hdr *hdr = mtod(m0, struct rfcomm_mcc_hdr*);
2799 struct rfcomm_mcc_pn *pn = (struct rfcomm_mcc_pn *)(hdr+1);
2800 ng_btsocket_rfcomm_pcb_t *pcb = NULL;
2803 mtx_assert(&s->session_mtx, MA_OWNED);
2805 NG_BTSOCKET_RFCOMM_INFO(
2806 "%s: Got MCC PN, dlci=%d, cr=%d, length=%d, flow_control=%#x, priority=%d, " \
2807 "ack_timer=%d, mtu=%d, max_retrans=%d, credits=%d, session state=%d, " \
2808 "flags=%#x, session mtu=%d, len=%d\n",
2809 __func__, pn->dlci, RFCOMM_CR(hdr->type),
2810 RFCOMM_MCC_LENGTH(hdr->length), pn->flow_control, pn->priority,
2811 pn->ack_timer, le16toh(pn->mtu), pn->max_retrans, pn->credits,
2812 s->state, s->flags, s->mtu, m0->m_pkthdr.len);
2814 if (pn->dlci == 0) {
2815 NG_BTSOCKET_RFCOMM_ERR("%s: Zero dlci in MCC PN\n", __func__);
2821 /* Check if we have this dlci */
2822 pcb = ng_btsocket_rfcomm_pcb_by_dlci(s, pn->dlci);
2824 mtx_lock(&pcb->pcb_mtx);
2826 if (RFCOMM_CR(hdr->type)) {
2828 ng_btsocket_rfcomm_set_pn(pcb, 1, pn->flow_control,
2829 pn->credits, pn->mtu);
2831 if (pcb->flags & NG_BTSOCKET_RFCOMM_DLC_CFC) {
2832 pn->flow_control = 0xe0;
2833 pn->credits = RFCOMM_DEFAULT_CREDITS;
2835 pn->flow_control = 0;
2839 hdr->type = RFCOMM_MKMCC_TYPE(0, RFCOMM_MCC_PN);
2840 error = ng_btsocket_rfcomm_send_uih(s,
2841 RFCOMM_MKADDRESS(INITIATOR(s), 0),
2844 /* PN Response - proceed with SABM. Timeout still set */
2845 if (pcb->state == NG_BTSOCKET_RFCOMM_DLC_CONFIGURING) {
2846 ng_btsocket_rfcomm_set_pn(pcb, 0,
2847 pn->flow_control, pn->credits, pn->mtu);
2849 pcb->state = NG_BTSOCKET_RFCOMM_DLC_CONNECTING;
2850 error = ng_btsocket_rfcomm_send_command(s,
2851 RFCOMM_FRAME_SABM, pn->dlci);
2853 NG_BTSOCKET_RFCOMM_WARN(
2854 "%s: Got PN response for dlci=%d in invalid state=%d\n",
2855 __func__, pn->dlci, pcb->state);
2860 mtx_unlock(&pcb->pcb_mtx);
2861 } else if (RFCOMM_CR(hdr->type)) {
2862 /* PN request to non-existing dlci - incoming connection */
2863 pcb = ng_btsocket_rfcomm_connect_ind(s,
2864 RFCOMM_SRVCHANNEL(pn->dlci));
2866 mtx_lock(&pcb->pcb_mtx);
2868 pcb->dlci = pn->dlci;
2870 ng_btsocket_rfcomm_set_pn(pcb, 1, pn->flow_control,
2871 pn->credits, pn->mtu);
2873 if (pcb->flags & NG_BTSOCKET_RFCOMM_DLC_CFC) {
2874 pn->flow_control = 0xe0;
2875 pn->credits = RFCOMM_DEFAULT_CREDITS;
2877 pn->flow_control = 0;
2881 hdr->type = RFCOMM_MKMCC_TYPE(0, RFCOMM_MCC_PN);
2882 error = ng_btsocket_rfcomm_send_uih(s,
2883 RFCOMM_MKADDRESS(INITIATOR(s), 0),
2887 ng_btsocket_rfcomm_timeout(pcb);
2888 pcb->state = NG_BTSOCKET_RFCOMM_DLC_CONNECTING;
2889 soisconnecting(pcb->so);
2891 ng_btsocket_rfcomm_pcb_kill(pcb, error);
2893 mtx_unlock(&pcb->pcb_mtx);
2895 /* Nobody is listen()ing on this channel */
2896 error = ng_btsocket_rfcomm_send_command(s,
2897 RFCOMM_FRAME_DM, pn->dlci);
2901 NG_FREE_M(m0); /* XXX ignore response to non-existing dlci */
2904 } /* ng_btsocket_rfcomm_receive_pn */
2907 * Set PN parameters for dlci. Caller must hold pcb->pcb_mtx.
2909 * From Bluetooth spec.
2911 * "... The CL1 - CL4 field is completely redefined. (In TS07.10 this defines
2912 * the convergence layer to use, which is not applicable to RFCOMM. In RFCOMM,
2913 * in Bluetooth versions up to 1.0B, this field was forced to 0).
2915 * In the PN request sent prior to a DLC establishment, this field must contain
2916 * the value 15 (0xF), indicating support of credit based flow control in the
2917 * sender. See Table 5.3 below. If the PN response contains any other value
2918 * than 14 (0xE) in this field, it is inferred that the peer RFCOMM entity is
2919 * not supporting the credit based flow control feature. (This is only possible
2920 * if the peer RFCOMM implementation is only conforming to Bluetooth version
2921 * 1.0B.) If a PN request is sent on an already open DLC, then this field must
2922 * contain the value zero; it is not possible to set initial credits more
2923 * than once per DLC activation. A responding implementation must set this
2924 * field in the PN response to 14 (0xE), if (and only if) the value in the PN
2925 * request was 15..."
2929 ng_btsocket_rfcomm_set_pn(ng_btsocket_rfcomm_pcb_p pcb, u_int8_t cr,
2930 u_int8_t flow_control, u_int8_t credits, u_int16_t mtu)
2932 mtx_assert(&pcb->pcb_mtx, MA_OWNED);
2934 pcb->mtu = le16toh(mtu);
2937 if (flow_control == 0xf0) {
2938 pcb->flags |= NG_BTSOCKET_RFCOMM_DLC_CFC;
2939 pcb->tx_cred = credits;
2941 pcb->flags &= ~NG_BTSOCKET_RFCOMM_DLC_CFC;
2945 if (flow_control == 0xe0) {
2946 pcb->flags |= NG_BTSOCKET_RFCOMM_DLC_CFC;
2947 pcb->tx_cred = credits;
2949 pcb->flags &= ~NG_BTSOCKET_RFCOMM_DLC_CFC;
2954 NG_BTSOCKET_RFCOMM_INFO(
2955 "%s: cr=%d, dlci=%d, state=%d, flags=%#x, mtu=%d, rx_cred=%d, tx_cred=%d\n",
2956 __func__, cr, pcb->dlci, pcb->state, pcb->flags, pcb->mtu,
2957 pcb->rx_cred, pcb->tx_cred);
2958 } /* ng_btsocket_rfcomm_set_pn */
2961 * Send RFCOMM SABM/DISC/UA/DM frames. Caller must hold s->session_mtx
2965 ng_btsocket_rfcomm_send_command(ng_btsocket_rfcomm_session_p s,
2966 u_int8_t type, u_int8_t dlci)
2968 struct rfcomm_cmd_hdr *hdr = NULL;
2969 struct mbuf *m = NULL;
2972 mtx_assert(&s->session_mtx, MA_OWNED);
2974 NG_BTSOCKET_RFCOMM_INFO(
2975 "%s: Sending command type %#x, session state=%d, flags=%#x, mtu=%d, dlci=%d\n",
2976 __func__, type, s->state, s->flags, s->mtu, dlci);
2979 case RFCOMM_FRAME_SABM:
2980 case RFCOMM_FRAME_DISC:
2984 case RFCOMM_FRAME_UA:
2985 case RFCOMM_FRAME_DM:
2990 panic("%s: Invalid frame type=%#x\n", __func__, type);
2995 MGETHDR(m, M_NOWAIT, MT_DATA);
2999 m->m_pkthdr.len = m->m_len = sizeof(*hdr);
3001 hdr = mtod(m, struct rfcomm_cmd_hdr *);
3002 hdr->address = RFCOMM_MKADDRESS(cr, dlci);
3003 hdr->control = RFCOMM_MKCONTROL(type, 1);
3004 hdr->length = RFCOMM_MKLEN8(0);
3005 hdr->fcs = ng_btsocket_rfcomm_fcs3((u_int8_t *) hdr);
3007 NG_BT_MBUFQ_ENQUEUE(&s->outq, m);
3010 } /* ng_btsocket_rfcomm_send_command */
3013 * Send RFCOMM UIH frame. Caller must hold s->session_mtx
3017 ng_btsocket_rfcomm_send_uih(ng_btsocket_rfcomm_session_p s, u_int8_t address,
3018 u_int8_t pf, u_int8_t credits, struct mbuf *data)
3020 struct rfcomm_frame_hdr *hdr = NULL;
3021 struct mbuf *m = NULL, *mcrc = NULL;
3024 mtx_assert(&s->session_mtx, MA_OWNED);
3026 MGETHDR(m, M_NOWAIT, MT_DATA);
3031 m->m_pkthdr.len = m->m_len = sizeof(*hdr);
3033 MGET(mcrc, M_NOWAIT, MT_DATA);
3040 /* Fill UIH frame header */
3041 hdr = mtod(m, struct rfcomm_frame_hdr *);
3042 hdr->address = address;
3043 hdr->control = RFCOMM_MKCONTROL(RFCOMM_FRAME_UIH, pf);
3046 mcrc->m_data[0] = ng_btsocket_rfcomm_fcs2((u_int8_t *) hdr);
3048 /* Put length back */
3049 length = (data != NULL)? data->m_pkthdr.len : 0;
3051 u_int16_t l = htole16(RFCOMM_MKLEN16(length));
3053 bcopy(&l, &hdr->length, sizeof(l));
3057 hdr->length = RFCOMM_MKLEN8(length);
3060 m->m_data[m->m_len] = credits;
3068 m->m_pkthdr.len += length;
3075 NG_BTSOCKET_RFCOMM_INFO(
3076 "%s: Sending UIH state=%d, flags=%#x, address=%d, length=%d, pf=%d, " \
3077 "credits=%d, len=%d\n",
3078 __func__, s->state, s->flags, address, length, pf, credits,
3081 NG_BT_MBUFQ_ENQUEUE(&s->outq, m);
3084 } /* ng_btsocket_rfcomm_send_uih */
3087 * Send MSC request. Caller must hold pcb->pcb_mtx and pcb->session->session_mtx
3091 ng_btsocket_rfcomm_send_msc(ng_btsocket_rfcomm_pcb_p pcb)
3093 struct mbuf *m = NULL;
3094 struct rfcomm_mcc_hdr *hdr = NULL;
3095 struct rfcomm_mcc_msc *msc = NULL;
3097 mtx_assert(&pcb->session->session_mtx, MA_OWNED);
3098 mtx_assert(&pcb->pcb_mtx, MA_OWNED);
3100 MGETHDR(m, M_NOWAIT, MT_DATA);
3104 m->m_pkthdr.len = m->m_len = sizeof(*hdr) + sizeof(*msc);
3106 hdr = mtod(m, struct rfcomm_mcc_hdr *);
3107 msc = (struct rfcomm_mcc_msc *)(hdr + 1);
3109 hdr->type = RFCOMM_MKMCC_TYPE(1, RFCOMM_MCC_MSC);
3110 hdr->length = RFCOMM_MKLEN8(sizeof(*msc));
3112 msc->address = RFCOMM_MKADDRESS(1, pcb->dlci);
3113 msc->modem = pcb->lmodem;
3115 NG_BTSOCKET_RFCOMM_INFO(
3116 "%s: Sending MSC dlci=%d, state=%d, flags=%#x, address=%d, modem=%#x\n",
3117 __func__, pcb->dlci, pcb->state, pcb->flags, msc->address,
3120 return (ng_btsocket_rfcomm_send_uih(pcb->session,
3121 RFCOMM_MKADDRESS(INITIATOR(pcb->session), 0), 0, 0, m));
3122 } /* ng_btsocket_rfcomm_send_msc */
3125 * Send PN request. Caller must hold pcb->pcb_mtx and pcb->session->session_mtx
3129 ng_btsocket_rfcomm_send_pn(ng_btsocket_rfcomm_pcb_p pcb)
3131 struct mbuf *m = NULL;
3132 struct rfcomm_mcc_hdr *hdr = NULL;
3133 struct rfcomm_mcc_pn *pn = NULL;
3135 mtx_assert(&pcb->session->session_mtx, MA_OWNED);
3136 mtx_assert(&pcb->pcb_mtx, MA_OWNED);
3138 MGETHDR(m, M_NOWAIT, MT_DATA);
3142 m->m_pkthdr.len = m->m_len = sizeof(*hdr) + sizeof(*pn);
3144 hdr = mtod(m, struct rfcomm_mcc_hdr *);
3145 pn = (struct rfcomm_mcc_pn *)(hdr + 1);
3147 hdr->type = RFCOMM_MKMCC_TYPE(1, RFCOMM_MCC_PN);
3148 hdr->length = RFCOMM_MKLEN8(sizeof(*pn));
3150 pn->dlci = pcb->dlci;
3153 * Set default DLCI priority as described in GSM 07.10
3154 * (ETSI TS 101 369) clause 5.6 page 42
3157 pn->priority = (pcb->dlci < 56)? (((pcb->dlci >> 3) << 3) + 7) : 61;
3159 pn->mtu = htole16(pcb->mtu);
3160 pn->max_retrans = 0;
3162 if (pcb->flags & NG_BTSOCKET_RFCOMM_DLC_CFC) {
3163 pn->flow_control = 0xf0;
3164 pn->credits = pcb->rx_cred;
3166 pn->flow_control = 0;
3170 NG_BTSOCKET_RFCOMM_INFO(
3171 "%s: Sending PN dlci=%d, state=%d, flags=%#x, mtu=%d, flow_control=%#x, " \
3172 "credits=%d\n", __func__, pcb->dlci, pcb->state, pcb->flags, pcb->mtu,
3173 pn->flow_control, pn->credits);
3175 return (ng_btsocket_rfcomm_send_uih(pcb->session,
3176 RFCOMM_MKADDRESS(INITIATOR(pcb->session), 0), 0, 0, m));
3177 } /* ng_btsocket_rfcomm_send_pn */
3180 * Calculate and send credits based on available space in receive buffer
3184 ng_btsocket_rfcomm_send_credits(ng_btsocket_rfcomm_pcb_p pcb)
3189 mtx_assert(&pcb->pcb_mtx, MA_OWNED);
3190 mtx_assert(&pcb->session->session_mtx, MA_OWNED);
3192 NG_BTSOCKET_RFCOMM_INFO(
3193 "%s: Sending more credits, dlci=%d, state=%d, flags=%#x, mtu=%d, " \
3194 "space=%ld, tx_cred=%d, rx_cred=%d\n",
3195 __func__, pcb->dlci, pcb->state, pcb->flags, pcb->mtu,
3196 sbspace(&pcb->so->so_rcv), pcb->tx_cred, pcb->rx_cred);
3198 credits = sbspace(&pcb->so->so_rcv) / pcb->mtu;
3200 if (pcb->rx_cred + credits > RFCOMM_MAX_CREDITS)
3201 credits = RFCOMM_MAX_CREDITS - pcb->rx_cred;
3203 error = ng_btsocket_rfcomm_send_uih(
3205 RFCOMM_MKADDRESS(INITIATOR(pcb->session),
3206 pcb->dlci), 1, credits, NULL);
3208 pcb->rx_cred += credits;
3210 NG_BTSOCKET_RFCOMM_INFO(
3211 "%s: Gave remote side %d more credits, dlci=%d, state=%d, flags=%#x, " \
3212 "rx_cred=%d, tx_cred=%d\n", __func__, credits, pcb->dlci, pcb->state,
3213 pcb->flags, pcb->rx_cred, pcb->tx_cred);
3215 NG_BTSOCKET_RFCOMM_ERR(
3216 "%s: Could not send credits, error=%d, dlci=%d, state=%d, flags=%#x, " \
3217 "mtu=%d, space=%ld, tx_cred=%d, rx_cred=%d\n",
3218 __func__, error, pcb->dlci, pcb->state,
3219 pcb->flags, pcb->mtu, sbspace(&pcb->so->so_rcv),
3220 pcb->tx_cred, pcb->rx_cred);
3224 } /* ng_btsocket_rfcomm_send_credits */
3226 /*****************************************************************************
3227 *****************************************************************************
3229 *****************************************************************************
3230 *****************************************************************************/
3233 * Send data from socket send buffer
3234 * Caller must hold pcb->pcb_mtx and pcb->session->session_mtx
3238 ng_btsocket_rfcomm_pcb_send(ng_btsocket_rfcomm_pcb_p pcb, int limit)
3240 struct mbuf *m = NULL;
3241 int sent, length, error;
3243 mtx_assert(&pcb->session->session_mtx, MA_OWNED);
3244 mtx_assert(&pcb->pcb_mtx, MA_OWNED);
3246 if (pcb->flags & NG_BTSOCKET_RFCOMM_DLC_CFC)
3247 limit = min(limit, pcb->tx_cred);
3248 else if (!(pcb->rmodem & RFCOMM_MODEM_FC))
3249 limit = min(limit, RFCOMM_MAX_CREDITS); /* XXX ??? */
3254 NG_BTSOCKET_RFCOMM_INFO(
3255 "%s: Could not send - remote flow control asserted, dlci=%d, flags=%#x, " \
3256 "rmodem=%#x, tx_cred=%d\n",
3257 __func__, pcb->dlci, pcb->flags, pcb->rmodem,
3263 for (error = 0, sent = 0; sent < limit; sent ++) {
3264 length = min(pcb->mtu, sbavail(&pcb->so->so_snd));
3268 /* Get the chunk from the socket's send buffer */
3269 m = ng_btsocket_rfcomm_prepare_packet(&pcb->so->so_snd, length);
3275 sbdrop(&pcb->so->so_snd, length);
3277 error = ng_btsocket_rfcomm_send_uih(pcb->session,
3278 RFCOMM_MKADDRESS(INITIATOR(pcb->session),
3279 pcb->dlci), 0, 0, m);
3284 if (pcb->flags & NG_BTSOCKET_RFCOMM_DLC_CFC)
3285 pcb->tx_cred -= sent;
3287 if (error == 0 && sent > 0) {
3288 pcb->flags &= ~NG_BTSOCKET_RFCOMM_DLC_SENDING;
3293 } /* ng_btsocket_rfcomm_pcb_send */
3296 * Unlink and disconnect DLC. If ng_btsocket_rfcomm_pcb_kill() returns
3297 * non zero value than socket has no reference and has to be detached.
3298 * Caller must hold pcb->pcb_mtx and pcb->session->session_mtx
3302 ng_btsocket_rfcomm_pcb_kill(ng_btsocket_rfcomm_pcb_p pcb, int error)
3304 ng_btsocket_rfcomm_session_p s = pcb->session;
3306 NG_BTSOCKET_RFCOMM_INFO(
3307 "%s: Killing DLC, so=%p, dlci=%d, state=%d, flags=%#x, error=%d\n",
3308 __func__, pcb->so, pcb->dlci, pcb->state, pcb->flags, error);
3310 if (pcb->session == NULL)
3311 panic("%s: DLC without session, pcb=%p, state=%d, flags=%#x\n",
3312 __func__, pcb, pcb->state, pcb->flags);
3314 mtx_assert(&pcb->session->session_mtx, MA_OWNED);
3315 mtx_assert(&pcb->pcb_mtx, MA_OWNED);
3317 if (pcb->flags & NG_BTSOCKET_RFCOMM_DLC_TIMO)
3318 ng_btsocket_rfcomm_untimeout(pcb);
3320 /* Detach DLC from the session. Does not matter which state DLC in */
3321 LIST_REMOVE(pcb, session_next);
3322 pcb->session = NULL;
3324 /* Change DLC state and wakeup all sleepers */
3325 pcb->state = NG_BTSOCKET_RFCOMM_DLC_CLOSED;
3326 pcb->so->so_error = error;
3327 soisdisconnected(pcb->so);
3328 wakeup(&pcb->state);
3330 /* Check if we have any DLCs left on the session */
3331 if (LIST_EMPTY(&s->dlcs) && INITIATOR(s)) {
3332 NG_BTSOCKET_RFCOMM_INFO(
3333 "%s: Disconnecting session, state=%d, flags=%#x, mtu=%d\n",
3334 __func__, s->state, s->flags, s->mtu);
3337 case NG_BTSOCKET_RFCOMM_SESSION_CLOSED:
3338 case NG_BTSOCKET_RFCOMM_SESSION_DISCONNECTING:
3340 * Do not have to do anything here. We can get here
3341 * when L2CAP connection was terminated or we have
3342 * received DISC on multiplexor channel
3346 case NG_BTSOCKET_RFCOMM_SESSION_OPEN:
3347 /* Send DISC on multiplexor channel */
3348 error = ng_btsocket_rfcomm_send_command(s,
3349 RFCOMM_FRAME_DISC, 0);
3351 s->state = NG_BTSOCKET_RFCOMM_SESSION_DISCONNECTING;
3356 case NG_BTSOCKET_RFCOMM_SESSION_CONNECTING:
3357 case NG_BTSOCKET_RFCOMM_SESSION_CONNECTED:
3358 s->state = NG_BTSOCKET_RFCOMM_SESSION_CLOSED;
3361 /* case NG_BTSOCKET_RFCOMM_SESSION_LISTENING: */
3363 panic("%s: Invalid session state=%d, flags=%#x\n",
3364 __func__, s->state, s->flags);
3368 ng_btsocket_rfcomm_task_wakeup();
3370 } /* ng_btsocket_rfcomm_pcb_kill */
3373 * Look for given dlci for given RFCOMM session. Caller must hold s->session_mtx
3376 static ng_btsocket_rfcomm_pcb_p
3377 ng_btsocket_rfcomm_pcb_by_dlci(ng_btsocket_rfcomm_session_p s, int dlci)
3379 ng_btsocket_rfcomm_pcb_p pcb = NULL;
3381 mtx_assert(&s->session_mtx, MA_OWNED);
3383 LIST_FOREACH(pcb, &s->dlcs, session_next)
3384 if (pcb->dlci == dlci)
3388 } /* ng_btsocket_rfcomm_pcb_by_dlci */
3391 * Look for socket that listens on given src address and given channel
3394 static ng_btsocket_rfcomm_pcb_p
3395 ng_btsocket_rfcomm_pcb_listener(bdaddr_p src, int channel)
3397 ng_btsocket_rfcomm_pcb_p pcb = NULL, pcb1 = NULL;
3399 mtx_lock(&ng_btsocket_rfcomm_sockets_mtx);
3401 LIST_FOREACH(pcb, &ng_btsocket_rfcomm_sockets, next) {
3402 if (pcb->channel != channel ||
3403 !(pcb->so->so_options & SO_ACCEPTCONN))
3406 if (bcmp(&pcb->src, src, sizeof(*src)) == 0)
3409 if (bcmp(&pcb->src, NG_HCI_BDADDR_ANY, sizeof(bdaddr_t)) == 0)
3413 mtx_unlock(&ng_btsocket_rfcomm_sockets_mtx);
3415 return ((pcb != NULL)? pcb : pcb1);
3416 } /* ng_btsocket_rfcomm_pcb_listener */
3418 /*****************************************************************************
3419 *****************************************************************************
3421 *****************************************************************************
3422 *****************************************************************************/
3425 * Set timeout. Caller MUST hold pcb_mtx
3429 ng_btsocket_rfcomm_timeout(ng_btsocket_rfcomm_pcb_p pcb)
3431 mtx_assert(&pcb->pcb_mtx, MA_OWNED);
3433 if (!(pcb->flags & NG_BTSOCKET_RFCOMM_DLC_TIMO)) {
3434 pcb->flags |= NG_BTSOCKET_RFCOMM_DLC_TIMO;
3435 pcb->flags &= ~NG_BTSOCKET_RFCOMM_DLC_TIMEDOUT;
3436 callout_reset(&pcb->timo, ng_btsocket_rfcomm_timo * hz,
3437 ng_btsocket_rfcomm_process_timeout, pcb);
3439 panic("%s: Duplicated socket timeout?!\n", __func__);
3440 } /* ng_btsocket_rfcomm_timeout */
3443 * Unset pcb timeout. Caller MUST hold pcb_mtx
3447 ng_btsocket_rfcomm_untimeout(ng_btsocket_rfcomm_pcb_p pcb)
3449 mtx_assert(&pcb->pcb_mtx, MA_OWNED);
3451 if (pcb->flags & NG_BTSOCKET_RFCOMM_DLC_TIMO) {
3452 callout_stop(&pcb->timo);
3453 pcb->flags &= ~NG_BTSOCKET_RFCOMM_DLC_TIMO;
3454 pcb->flags &= ~NG_BTSOCKET_RFCOMM_DLC_TIMEDOUT;
3456 panic("%s: No socket timeout?!\n", __func__);
3457 } /* ng_btsocket_rfcomm_timeout */
3460 * Process pcb timeout
3464 ng_btsocket_rfcomm_process_timeout(void *xpcb)
3466 ng_btsocket_rfcomm_pcb_p pcb = (ng_btsocket_rfcomm_pcb_p) xpcb;
3468 mtx_assert(&pcb->pcb_mtx, MA_OWNED);
3470 NG_BTSOCKET_RFCOMM_INFO(
3471 "%s: Timeout, so=%p, dlci=%d, state=%d, flags=%#x\n",
3472 __func__, pcb->so, pcb->dlci, pcb->state, pcb->flags);
3474 pcb->flags &= ~NG_BTSOCKET_RFCOMM_DLC_TIMO;
3475 pcb->flags |= NG_BTSOCKET_RFCOMM_DLC_TIMEDOUT;
3477 switch (pcb->state) {
3478 case NG_BTSOCKET_RFCOMM_DLC_CONFIGURING:
3479 case NG_BTSOCKET_RFCOMM_DLC_CONNECTING:
3480 pcb->state = NG_BTSOCKET_RFCOMM_DLC_DISCONNECTING;
3483 case NG_BTSOCKET_RFCOMM_DLC_W4_CONNECT:
3484 case NG_BTSOCKET_RFCOMM_DLC_DISCONNECTING:
3489 "%s: DLC timeout in invalid state, dlci=%d, state=%d, flags=%#x\n",
3490 __func__, pcb->dlci, pcb->state, pcb->flags);
3494 ng_btsocket_rfcomm_task_wakeup();
3495 } /* ng_btsocket_rfcomm_process_timeout */
3498 * Get up to length bytes from the socket buffer
3501 static struct mbuf *
3502 ng_btsocket_rfcomm_prepare_packet(struct sockbuf *sb, int length)
3504 struct mbuf *top = NULL, *m = NULL, *n = NULL, *nextpkt = NULL;
3505 int mlen, noff, len;
3507 MGETHDR(top, M_NOWAIT, MT_DATA);
3511 top->m_pkthdr.len = length;
3517 nextpkt = n->m_nextpkt;
3520 while (length > 0 && n != NULL) {
3521 len = min(mlen - m->m_len, n->m_len - noff);
3525 bcopy(mtod(n, caddr_t)+noff, mtod(m, caddr_t)+m->m_len, len);
3530 if (length > 0 && m->m_len == mlen) {
3531 MGET(m->m_next, M_NOWAIT, MT_DATA);
3532 if (m->m_next == NULL) {
3542 if (noff == n->m_len) {
3549 nextpkt = (n != NULL)? n->m_nextpkt : NULL;
3554 panic("%s: length=%d\n", __func__, length);
3555 if (length > 0 && n == NULL)
3556 panic("%s: bogus length=%d, n=%p\n", __func__, length, n);
3559 } /* ng_btsocket_rfcomm_prepare_packet */