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_init_mtx(&pcb->timo, &pcb->pcb_mtx, 0);
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, flags);
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 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 = NULL;
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 /* Check if there is a complete L2CAP connection in the queue */
1418 if ((error = s0->l2so->so_error) != 0) {
1419 NG_BTSOCKET_RFCOMM_ERR(
1420 "%s: Could not accept connection on L2CAP socket, error=%d\n", __func__, error);
1421 s0->l2so->so_error = 0;
1427 if (TAILQ_EMPTY(&s0->l2so->so_comp)) {
1429 if (s0->l2so->so_rcv.sb_state & SBS_CANTRCVMORE)
1430 return (ECONNABORTED);
1431 return (EWOULDBLOCK);
1434 /* Accept incoming L2CAP connection */
1435 l2so = TAILQ_FIRST(&s0->l2so->so_comp);
1437 panic("%s: l2so == NULL\n", __func__);
1439 TAILQ_REMOVE(&s0->l2so->so_comp, l2so, so_list);
1440 s0->l2so->so_qlen --;
1441 l2so->so_qstate &= ~SQ_COMP;
1442 l2so->so_head = NULL;
1445 l2so->so_state |= SS_NBIO;
1449 error = soaccept(l2so, (struct sockaddr **) &l2sa);
1451 NG_BTSOCKET_RFCOMM_ERR(
1452 "%s: soaccept() on L2CAP socket failed, error=%d\n", __func__, error);
1459 * Check if there is already active RFCOMM session between two devices.
1460 * If so then close L2CAP connection. We only support one RFCOMM session
1461 * between each pair of devices. Note that here we assume session in any
1462 * state. The session even could be in the middle of disconnecting.
1465 l2pcb = so2l2cap_pcb(l2so);
1466 s = ng_btsocket_rfcomm_session_by_addr(&l2pcb->src, &l2pcb->dst);
1468 /* Create a new RFCOMM session */
1469 error = ng_btsocket_rfcomm_session_create(&s, l2so, NULL, NULL,
1470 curthread /* XXX */);
1472 mtx_lock(&s->session_mtx);
1475 s->state = NG_BTSOCKET_RFCOMM_SESSION_CONNECTED;
1478 * Adjust MTU on incoming connection. Reserve 5 bytes:
1479 * RFCOMM frame header, one extra byte for length and
1480 * one extra byte for credits.
1483 s->mtu = min(l2pcb->imtu, l2pcb->omtu) -
1484 sizeof(struct rfcomm_frame_hdr) - 1 - 1;
1486 mtx_unlock(&s->session_mtx);
1488 NG_BTSOCKET_RFCOMM_ALERT(
1489 "%s: Failed to create new RFCOMM session, error=%d\n", __func__, error);
1494 NG_BTSOCKET_RFCOMM_WARN(
1495 "%s: Rejecting duplicating RFCOMM session between src=%x:%x:%x:%x:%x:%x and " \
1496 "dst=%x:%x:%x:%x:%x:%x, state=%d, flags=%#x\n", __func__,
1497 l2pcb->src.b[5], l2pcb->src.b[4], l2pcb->src.b[3],
1498 l2pcb->src.b[2], l2pcb->src.b[1], l2pcb->src.b[0],
1499 l2pcb->dst.b[5], l2pcb->dst.b[4], l2pcb->dst.b[3],
1500 l2pcb->dst.b[2], l2pcb->dst.b[1], l2pcb->dst.b[0],
1501 s->state, s->flags);
1508 } /* ng_btsocket_rfcomm_session_accept */
1511 * Process connect() on RFCOMM session
1512 * XXX FIXME locking for "l2so"?
1516 ng_btsocket_rfcomm_session_connect(ng_btsocket_rfcomm_session_p s)
1518 ng_btsocket_l2cap_pcb_p l2pcb = so2l2cap_pcb(s->l2so);
1521 mtx_assert(&s->session_mtx, MA_OWNED);
1523 /* First check if connection has failed */
1524 if ((error = s->l2so->so_error) != 0) {
1525 s->l2so->so_error = 0;
1527 NG_BTSOCKET_RFCOMM_ERR(
1528 "%s: Could not connect RFCOMM session, error=%d, state=%d, flags=%#x\n",
1529 __func__, error, s->state, s->flags);
1534 /* Is connection still in progress? */
1535 if (s->l2so->so_state & SS_ISCONNECTING)
1539 * If we got here then we are connected. Send SABM on DLCI 0 to
1540 * open multiplexor channel.
1544 s->state = NG_BTSOCKET_RFCOMM_SESSION_CONNECTED;
1547 * Adjust MTU on outgoing connection. Reserve 5 bytes: RFCOMM
1548 * frame header, one extra byte for length and one extra byte
1552 s->mtu = min(l2pcb->imtu, l2pcb->omtu) -
1553 sizeof(struct rfcomm_frame_hdr) - 1 - 1;
1555 error = ng_btsocket_rfcomm_send_command(s,RFCOMM_FRAME_SABM,0);
1557 error = ng_btsocket_rfcomm_task_wakeup();
1561 }/* ng_btsocket_rfcomm_session_connect */
1564 * Receive data on RFCOMM session
1565 * XXX FIXME locking for "l2so"?
1569 ng_btsocket_rfcomm_session_receive(ng_btsocket_rfcomm_session_p s)
1571 struct mbuf *m = NULL;
1573 int more, flags, error;
1575 mtx_assert(&s->session_mtx, MA_OWNED);
1577 /* Can we read from the L2CAP socket? */
1578 if (!soreadable(s->l2so))
1581 /* First check for error on L2CAP socket */
1582 if ((error = s->l2so->so_error) != 0) {
1583 s->l2so->so_error = 0;
1585 NG_BTSOCKET_RFCOMM_ERR(
1586 "%s: Could not receive data from L2CAP socket, error=%d, state=%d, flags=%#x\n",
1587 __func__, error, s->state, s->flags);
1593 * Read all packets from the L2CAP socket.
1594 * XXX FIXME/VERIFY is that correct? For now use m->m_nextpkt as
1595 * indication that there is more packets on the socket's buffer.
1596 * Also what should we use in uio.uio_resid?
1597 * May be s->mtu + sizeof(struct rfcomm_frame_hdr) + 1 + 1?
1600 for (more = 1; more; ) {
1601 /* Try to get next packet from socket */
1602 bzero(&uio, sizeof(uio));
1603 /* uio.uio_td = NULL; */
1604 uio.uio_resid = 1000000000;
1605 flags = MSG_DONTWAIT;
1608 error = soreceive(s->l2so, NULL, &uio, &m,
1609 (struct mbuf **) NULL, &flags);
1611 if (error == EWOULDBLOCK)
1612 return (0); /* XXX can happen? */
1614 NG_BTSOCKET_RFCOMM_ERR(
1615 "%s: Could not receive data from L2CAP socket, error=%d\n", __func__, error);
1620 more = (m->m_nextpkt != NULL);
1621 m->m_nextpkt = NULL;
1623 ng_btsocket_rfcomm_receive_frame(s, m);
1627 } /* ng_btsocket_rfcomm_session_receive */
1630 * Send data on RFCOMM session
1631 * XXX FIXME locking for "l2so"?
1635 ng_btsocket_rfcomm_session_send(ng_btsocket_rfcomm_session_p s)
1637 struct mbuf *m = NULL;
1640 mtx_assert(&s->session_mtx, MA_OWNED);
1642 /* Send as much as we can from the session queue */
1643 while (sowriteable(s->l2so)) {
1644 /* Check if socket still OK */
1645 if ((error = s->l2so->so_error) != 0) {
1646 s->l2so->so_error = 0;
1648 NG_BTSOCKET_RFCOMM_ERR(
1649 "%s: Detected error=%d on L2CAP socket, state=%d, flags=%#x\n",
1650 __func__, error, s->state, s->flags);
1655 NG_BT_MBUFQ_DEQUEUE(&s->outq, m);
1657 return (0); /* we are done */
1659 /* Call send function on the L2CAP socket */
1660 error = (*s->l2so->so_proto->pr_usrreqs->pru_send)(s->l2so,
1661 0, m, NULL, NULL, curthread /* XXX */);
1663 NG_BTSOCKET_RFCOMM_ERR(
1664 "%s: Could not send data to L2CAP socket, error=%d\n", __func__, error);
1671 } /* ng_btsocket_rfcomm_session_send */
1674 * Close and disconnect all DLCs for the given session. Caller must hold
1675 * s->sesson_mtx. Will wakeup session.
1679 ng_btsocket_rfcomm_session_clean(ng_btsocket_rfcomm_session_p s)
1681 ng_btsocket_rfcomm_pcb_p pcb = NULL, pcb_next = NULL;
1684 mtx_assert(&s->session_mtx, MA_OWNED);
1687 * Note: cannot use LIST_FOREACH because ng_btsocket_rfcomm_pcb_kill
1688 * will unlink DLC from the session
1691 for (pcb = LIST_FIRST(&s->dlcs); pcb != NULL; ) {
1692 mtx_lock(&pcb->pcb_mtx);
1693 pcb_next = LIST_NEXT(pcb, session_next);
1695 NG_BTSOCKET_RFCOMM_INFO(
1696 "%s: Disconnecting dlci=%d, state=%d, flags=%#x\n",
1697 __func__, pcb->dlci, pcb->state, pcb->flags);
1699 if (pcb->state == NG_BTSOCKET_RFCOMM_DLC_CONNECTED)
1702 error = ECONNREFUSED;
1704 ng_btsocket_rfcomm_pcb_kill(pcb, error);
1706 mtx_unlock(&pcb->pcb_mtx);
1709 } /* ng_btsocket_rfcomm_session_clean */
1712 * Process all DLCs on the session. Caller MUST hold s->session_mtx.
1716 ng_btsocket_rfcomm_session_process_pcb(ng_btsocket_rfcomm_session_p s)
1718 ng_btsocket_rfcomm_pcb_p pcb = NULL, pcb_next = NULL;
1721 mtx_assert(&s->session_mtx, MA_OWNED);
1724 * Note: cannot use LIST_FOREACH because ng_btsocket_rfcomm_pcb_kill
1725 * will unlink DLC from the session
1728 for (pcb = LIST_FIRST(&s->dlcs); pcb != NULL; ) {
1729 mtx_lock(&pcb->pcb_mtx);
1730 pcb_next = LIST_NEXT(pcb, session_next);
1732 switch (pcb->state) {
1735 * If DLC in W4_CONNECT state then we should check for both
1736 * timeout and detach.
1739 case NG_BTSOCKET_RFCOMM_DLC_W4_CONNECT:
1740 if (pcb->flags & NG_BTSOCKET_RFCOMM_DLC_DETACHED)
1741 ng_btsocket_rfcomm_pcb_kill(pcb, 0);
1742 else if (pcb->flags & NG_BTSOCKET_RFCOMM_DLC_TIMEDOUT)
1743 ng_btsocket_rfcomm_pcb_kill(pcb, ETIMEDOUT);
1747 * If DLC in CONFIGURING or CONNECTING state then we only
1748 * should check for timeout. If detach() was called then
1749 * DLC will be moved into DISCONNECTING state.
1752 case NG_BTSOCKET_RFCOMM_DLC_CONFIGURING:
1753 case NG_BTSOCKET_RFCOMM_DLC_CONNECTING:
1754 if (pcb->flags & NG_BTSOCKET_RFCOMM_DLC_TIMEDOUT)
1755 ng_btsocket_rfcomm_pcb_kill(pcb, ETIMEDOUT);
1759 * If DLC in CONNECTED state then we need to send data (if any)
1760 * from the socket's send queue. Note that we will send data
1761 * from either all sockets or none. This may overload session's
1762 * outgoing queue (but we do not check for that).
1764 * XXX FIXME need scheduler for RFCOMM sockets
1767 case NG_BTSOCKET_RFCOMM_DLC_CONNECTED:
1768 error = ng_btsocket_rfcomm_pcb_send(pcb, ALOT);
1770 ng_btsocket_rfcomm_pcb_kill(pcb, error);
1774 * If DLC in DISCONNECTING state then we must send DISC frame.
1775 * Note that if DLC has timeout set then we do not need to
1776 * resend DISC frame.
1778 * XXX FIXME need to drain all data from the socket's queue
1779 * if LINGER option was set
1782 case NG_BTSOCKET_RFCOMM_DLC_DISCONNECTING:
1783 if (!(pcb->flags & NG_BTSOCKET_RFCOMM_DLC_TIMO)) {
1784 error = ng_btsocket_rfcomm_send_command(
1785 pcb->session, RFCOMM_FRAME_DISC,
1788 ng_btsocket_rfcomm_timeout(pcb);
1790 ng_btsocket_rfcomm_pcb_kill(pcb, error);
1791 } else if (pcb->flags & NG_BTSOCKET_RFCOMM_DLC_TIMEDOUT)
1792 ng_btsocket_rfcomm_pcb_kill(pcb, ETIMEDOUT);
1795 /* case NG_BTSOCKET_RFCOMM_DLC_CLOSED: */
1797 panic("%s: Invalid DLC state=%d, flags=%#x\n",
1798 __func__, pcb->state, pcb->flags);
1802 mtx_unlock(&pcb->pcb_mtx);
1805 } /* ng_btsocket_rfcomm_session_process_pcb */
1808 * Find RFCOMM session between "src" and "dst".
1809 * Caller MUST hold ng_btsocket_rfcomm_sessions_mtx.
1812 static ng_btsocket_rfcomm_session_p
1813 ng_btsocket_rfcomm_session_by_addr(bdaddr_p src, bdaddr_p dst)
1815 ng_btsocket_rfcomm_session_p s = NULL;
1816 ng_btsocket_l2cap_pcb_p l2pcb = NULL;
1819 mtx_assert(&ng_btsocket_rfcomm_sessions_mtx, MA_OWNED);
1821 any_src = (bcmp(src, NG_HCI_BDADDR_ANY, sizeof(*src)) == 0);
1823 LIST_FOREACH(s, &ng_btsocket_rfcomm_sessions, next) {
1824 l2pcb = so2l2cap_pcb(s->l2so);
1826 if ((any_src || bcmp(&l2pcb->src, src, sizeof(*src)) == 0) &&
1827 bcmp(&l2pcb->dst, dst, sizeof(*dst)) == 0)
1832 } /* ng_btsocket_rfcomm_session_by_addr */
1834 /*****************************************************************************
1835 *****************************************************************************
1837 *****************************************************************************
1838 *****************************************************************************/
1841 * Process incoming RFCOMM frame. Caller must hold s->session_mtx.
1842 * XXX FIXME check frame length
1846 ng_btsocket_rfcomm_receive_frame(ng_btsocket_rfcomm_session_p s,
1849 struct rfcomm_frame_hdr *hdr = NULL;
1850 struct mbuf *m = NULL;
1852 u_int8_t dlci, type;
1855 mtx_assert(&s->session_mtx, MA_OWNED);
1857 /* Pullup as much as we can into first mbuf (for direct access) */
1858 length = min(m0->m_pkthdr.len, MHLEN);
1859 if (m0->m_len < length) {
1860 if ((m0 = m_pullup(m0, length)) == NULL) {
1861 NG_BTSOCKET_RFCOMM_ALERT(
1862 "%s: m_pullup(%d) failed\n", __func__, length);
1868 hdr = mtod(m0, struct rfcomm_frame_hdr *);
1869 dlci = RFCOMM_DLCI(hdr->address);
1870 type = RFCOMM_TYPE(hdr->control);
1872 /* Test EA bit in length. If not set then we have 2 bytes of length */
1873 if (!RFCOMM_EA(hdr->length)) {
1874 bcopy(&hdr->length, &length, sizeof(length));
1875 length = le16toh(length) >> 1;
1876 m_adj(m0, sizeof(*hdr) + 1);
1878 length = hdr->length >> 1;
1879 m_adj(m0, sizeof(*hdr));
1882 NG_BTSOCKET_RFCOMM_INFO(
1883 "%s: Got frame type=%#x, dlci=%d, length=%d, cr=%d, pf=%d, len=%d\n",
1884 __func__, type, dlci, length, RFCOMM_CR(hdr->address),
1885 RFCOMM_PF(hdr->control), m0->m_pkthdr.len);
1888 * Get FCS (the last byte in the frame)
1889 * XXX this will not work if mbuf chain ends with empty mbuf.
1890 * XXX let's hope it never happens :)
1893 for (m = m0; m->m_next != NULL; m = m->m_next)
1896 panic("%s: Empty mbuf at the end of the chain, len=%d\n",
1897 __func__, m->m_len);
1900 * Check FCS. We only need to calculate FCS on first 2 or 3 bytes
1901 * and already m_pullup'ed mbuf chain, so it should be safe.
1904 if (ng_btsocket_rfcomm_check_fcs((u_int8_t *) hdr, type, m->m_data[m->m_len - 1])) {
1905 NG_BTSOCKET_RFCOMM_ERR(
1906 "%s: Invalid RFCOMM packet. Bad checksum\n", __func__);
1912 m_adj(m0, -1); /* Trim FCS byte */
1915 * Process RFCOMM frame.
1917 * From TS 07.10 spec
1919 * "... In the case where a SABM or DISC command with the P bit set
1920 * to 0 is received then the received frame shall be discarded..."
1922 * "... If a unsolicited DM response is received then the frame shall
1923 * be processed irrespective of the P/F setting... "
1925 * "... The station may transmit response frames with the F bit set
1926 * to 0 at any opportunity on an asynchronous basis. However, in the
1927 * case where a UA response is received with the F bit set to 0 then
1928 * the received frame shall be discarded..."
1930 * From Bluetooth spec
1932 * "... When credit based flow control is being used, the meaning of
1933 * the P/F bit in the control field of the RFCOMM header is redefined
1934 * for UIH frames..."
1938 case RFCOMM_FRAME_SABM:
1939 if (RFCOMM_PF(hdr->control))
1940 error = ng_btsocket_rfcomm_receive_sabm(s, dlci);
1943 case RFCOMM_FRAME_DISC:
1944 if (RFCOMM_PF(hdr->control))
1945 error = ng_btsocket_rfcomm_receive_disc(s, dlci);
1948 case RFCOMM_FRAME_UA:
1949 if (RFCOMM_PF(hdr->control))
1950 error = ng_btsocket_rfcomm_receive_ua(s, dlci);
1953 case RFCOMM_FRAME_DM:
1954 error = ng_btsocket_rfcomm_receive_dm(s, dlci);
1957 case RFCOMM_FRAME_UIH:
1959 error = ng_btsocket_rfcomm_receive_mcc(s, m0);
1961 error = ng_btsocket_rfcomm_receive_uih(s, dlci,
1962 RFCOMM_PF(hdr->control), m0);
1968 NG_BTSOCKET_RFCOMM_ERR(
1969 "%s: Invalid RFCOMM packet. Unknown type=%#x\n", __func__, type);
1977 } /* ng_btsocket_rfcomm_receive_frame */
1980 * Process RFCOMM SABM frame
1984 ng_btsocket_rfcomm_receive_sabm(ng_btsocket_rfcomm_session_p s, int dlci)
1986 ng_btsocket_rfcomm_pcb_p pcb = NULL;
1989 mtx_assert(&s->session_mtx, MA_OWNED);
1991 NG_BTSOCKET_RFCOMM_INFO(
1992 "%s: Got SABM, session state=%d, flags=%#x, mtu=%d, dlci=%d\n",
1993 __func__, s->state, s->flags, s->mtu, dlci);
1995 /* DLCI == 0 means open multiplexor channel */
1998 case NG_BTSOCKET_RFCOMM_SESSION_CONNECTED:
1999 case NG_BTSOCKET_RFCOMM_SESSION_OPEN:
2000 error = ng_btsocket_rfcomm_send_command(s,
2001 RFCOMM_FRAME_UA, dlci);
2003 s->state = NG_BTSOCKET_RFCOMM_SESSION_OPEN;
2004 ng_btsocket_rfcomm_connect_cfm(s);
2006 s->state = NG_BTSOCKET_RFCOMM_SESSION_CLOSED;
2007 ng_btsocket_rfcomm_session_clean(s);
2012 NG_BTSOCKET_RFCOMM_WARN(
2013 "%s: Got SABM for session in invalid state state=%d, flags=%#x\n",
2014 __func__, s->state, s->flags);
2022 /* Make sure multiplexor channel is open */
2023 if (s->state != NG_BTSOCKET_RFCOMM_SESSION_OPEN) {
2024 NG_BTSOCKET_RFCOMM_ERR(
2025 "%s: Got SABM for dlci=%d with mulitplexor channel closed, state=%d, " \
2026 "flags=%#x\n", __func__, dlci, s->state, s->flags);
2032 * Check if we have this DLCI. This might happen when remote
2033 * peer uses PN command before actual open (SABM) happens.
2036 pcb = ng_btsocket_rfcomm_pcb_by_dlci(s, dlci);
2038 mtx_lock(&pcb->pcb_mtx);
2040 if (pcb->state != NG_BTSOCKET_RFCOMM_DLC_CONNECTING) {
2041 NG_BTSOCKET_RFCOMM_ERR(
2042 "%s: Got SABM for dlci=%d in invalid state=%d, flags=%#x\n",
2043 __func__, dlci, pcb->state, pcb->flags);
2044 mtx_unlock(&pcb->pcb_mtx);
2049 ng_btsocket_rfcomm_untimeout(pcb);
2051 error = ng_btsocket_rfcomm_send_command(s,RFCOMM_FRAME_UA,dlci);
2053 error = ng_btsocket_rfcomm_send_msc(pcb);
2056 pcb->state = NG_BTSOCKET_RFCOMM_DLC_CONNECTED;
2057 soisconnected(pcb->so);
2059 ng_btsocket_rfcomm_pcb_kill(pcb, error);
2061 mtx_unlock(&pcb->pcb_mtx);
2067 * We do not have requested DLCI, so it must be an incoming connection
2068 * with default parameters. Try to accept it.
2071 pcb = ng_btsocket_rfcomm_connect_ind(s, RFCOMM_SRVCHANNEL(dlci));
2073 mtx_lock(&pcb->pcb_mtx);
2077 error = ng_btsocket_rfcomm_send_command(s,RFCOMM_FRAME_UA,dlci);
2079 error = ng_btsocket_rfcomm_send_msc(pcb);
2082 pcb->state = NG_BTSOCKET_RFCOMM_DLC_CONNECTED;
2083 soisconnected(pcb->so);
2085 ng_btsocket_rfcomm_pcb_kill(pcb, error);
2087 mtx_unlock(&pcb->pcb_mtx);
2089 /* Nobody is listen()ing on the requested DLCI */
2090 error = ng_btsocket_rfcomm_send_command(s,RFCOMM_FRAME_DM,dlci);
2093 } /* ng_btsocket_rfcomm_receive_sabm */
2096 * Process RFCOMM DISC frame
2100 ng_btsocket_rfcomm_receive_disc(ng_btsocket_rfcomm_session_p s, int dlci)
2102 ng_btsocket_rfcomm_pcb_p pcb = NULL;
2105 mtx_assert(&s->session_mtx, MA_OWNED);
2107 NG_BTSOCKET_RFCOMM_INFO(
2108 "%s: Got DISC, session state=%d, flags=%#x, mtu=%d, dlci=%d\n",
2109 __func__, s->state, s->flags, s->mtu, dlci);
2111 /* DLCI == 0 means close multiplexor channel */
2113 /* XXX FIXME assume that remote side will close the socket */
2114 error = ng_btsocket_rfcomm_send_command(s, RFCOMM_FRAME_UA, 0);
2116 if (s->state == NG_BTSOCKET_RFCOMM_SESSION_DISCONNECTING)
2117 s->state = NG_BTSOCKET_RFCOMM_SESSION_CLOSED; /* XXX */
2119 s->state = NG_BTSOCKET_RFCOMM_SESSION_DISCONNECTING;
2121 s->state = NG_BTSOCKET_RFCOMM_SESSION_CLOSED; /* XXX */
2123 ng_btsocket_rfcomm_session_clean(s);
2125 pcb = ng_btsocket_rfcomm_pcb_by_dlci(s, dlci);
2129 mtx_lock(&pcb->pcb_mtx);
2131 NG_BTSOCKET_RFCOMM_INFO(
2132 "%s: Got DISC for dlci=%d, state=%d, flags=%#x\n",
2133 __func__, dlci, pcb->state, pcb->flags);
2135 error = ng_btsocket_rfcomm_send_command(s,
2136 RFCOMM_FRAME_UA, dlci);
2138 if (pcb->state == NG_BTSOCKET_RFCOMM_DLC_CONNECTED)
2143 ng_btsocket_rfcomm_pcb_kill(pcb, err);
2145 mtx_unlock(&pcb->pcb_mtx);
2147 NG_BTSOCKET_RFCOMM_WARN(
2148 "%s: Got DISC for non-existing dlci=%d\n", __func__, dlci);
2150 error = ng_btsocket_rfcomm_send_command(s,
2151 RFCOMM_FRAME_DM, dlci);
2156 } /* ng_btsocket_rfcomm_receive_disc */
2159 * Process RFCOMM UA frame
2163 ng_btsocket_rfcomm_receive_ua(ng_btsocket_rfcomm_session_p s, int dlci)
2165 ng_btsocket_rfcomm_pcb_p pcb = NULL;
2168 mtx_assert(&s->session_mtx, MA_OWNED);
2170 NG_BTSOCKET_RFCOMM_INFO(
2171 "%s: Got UA, session state=%d, flags=%#x, mtu=%d, dlci=%d\n",
2172 __func__, s->state, s->flags, s->mtu, dlci);
2174 /* dlci == 0 means multiplexor channel */
2177 case NG_BTSOCKET_RFCOMM_SESSION_CONNECTED:
2178 s->state = NG_BTSOCKET_RFCOMM_SESSION_OPEN;
2179 ng_btsocket_rfcomm_connect_cfm(s);
2182 case NG_BTSOCKET_RFCOMM_SESSION_DISCONNECTING:
2183 s->state = NG_BTSOCKET_RFCOMM_SESSION_CLOSED;
2184 ng_btsocket_rfcomm_session_clean(s);
2188 NG_BTSOCKET_RFCOMM_WARN(
2189 "%s: Got UA for session in invalid state=%d(%d), flags=%#x, mtu=%d\n",
2190 __func__, s->state, INITIATOR(s), s->flags,
2199 /* Check if we have this DLCI */
2200 pcb = ng_btsocket_rfcomm_pcb_by_dlci(s, dlci);
2202 mtx_lock(&pcb->pcb_mtx);
2204 NG_BTSOCKET_RFCOMM_INFO(
2205 "%s: Got UA for dlci=%d, state=%d, flags=%#x\n",
2206 __func__, dlci, pcb->state, pcb->flags);
2208 switch (pcb->state) {
2209 case NG_BTSOCKET_RFCOMM_DLC_CONNECTING:
2210 ng_btsocket_rfcomm_untimeout(pcb);
2212 error = ng_btsocket_rfcomm_send_msc(pcb);
2214 pcb->state = NG_BTSOCKET_RFCOMM_DLC_CONNECTED;
2215 soisconnected(pcb->so);
2219 case NG_BTSOCKET_RFCOMM_DLC_DISCONNECTING:
2220 ng_btsocket_rfcomm_pcb_kill(pcb, 0);
2224 NG_BTSOCKET_RFCOMM_WARN(
2225 "%s: Got UA for dlci=%d in invalid state=%d, flags=%#x\n",
2226 __func__, dlci, pcb->state, pcb->flags);
2231 mtx_unlock(&pcb->pcb_mtx);
2233 NG_BTSOCKET_RFCOMM_WARN(
2234 "%s: Got UA for non-existing dlci=%d\n", __func__, dlci);
2236 error = ng_btsocket_rfcomm_send_command(s,RFCOMM_FRAME_DM,dlci);
2240 } /* ng_btsocket_rfcomm_receive_ua */
2243 * Process RFCOMM DM frame
2247 ng_btsocket_rfcomm_receive_dm(ng_btsocket_rfcomm_session_p s, int dlci)
2249 ng_btsocket_rfcomm_pcb_p pcb = NULL;
2252 mtx_assert(&s->session_mtx, MA_OWNED);
2254 NG_BTSOCKET_RFCOMM_INFO(
2255 "%s: Got DM, session state=%d, flags=%#x, mtu=%d, dlci=%d\n",
2256 __func__, s->state, s->flags, s->mtu, dlci);
2258 /* DLCI == 0 means multiplexor channel */
2260 /* Disconnect all dlc's on the session */
2261 s->state = NG_BTSOCKET_RFCOMM_SESSION_CLOSED;
2262 ng_btsocket_rfcomm_session_clean(s);
2264 pcb = ng_btsocket_rfcomm_pcb_by_dlci(s, dlci);
2266 mtx_lock(&pcb->pcb_mtx);
2268 NG_BTSOCKET_RFCOMM_INFO(
2269 "%s: Got DM for dlci=%d, state=%d, flags=%#x\n",
2270 __func__, dlci, pcb->state, pcb->flags);
2272 if (pcb->state == NG_BTSOCKET_RFCOMM_DLC_CONNECTED)
2275 error = ECONNREFUSED;
2277 ng_btsocket_rfcomm_pcb_kill(pcb, error);
2279 mtx_unlock(&pcb->pcb_mtx);
2281 NG_BTSOCKET_RFCOMM_WARN(
2282 "%s: Got DM for non-existing dlci=%d\n", __func__, dlci);
2286 } /* ng_btsocket_rfcomm_receive_dm */
2289 * Process RFCOMM UIH frame (data)
2293 ng_btsocket_rfcomm_receive_uih(ng_btsocket_rfcomm_session_p s, int dlci,
2294 int pf, struct mbuf *m0)
2296 ng_btsocket_rfcomm_pcb_p pcb = NULL;
2299 mtx_assert(&s->session_mtx, MA_OWNED);
2301 NG_BTSOCKET_RFCOMM_INFO(
2302 "%s: Got UIH, session state=%d, flags=%#x, mtu=%d, dlci=%d, pf=%d, len=%d\n",
2303 __func__, s->state, s->flags, s->mtu, dlci, pf,
2306 /* XXX should we do it here? Check for session flow control */
2307 if (s->flags & NG_BTSOCKET_RFCOMM_SESSION_LFC) {
2308 NG_BTSOCKET_RFCOMM_WARN(
2309 "%s: Got UIH with session flow control asserted, state=%d, flags=%#x\n",
2310 __func__, s->state, s->flags);
2314 /* Check if we have this dlci */
2315 pcb = ng_btsocket_rfcomm_pcb_by_dlci(s, dlci);
2317 NG_BTSOCKET_RFCOMM_WARN(
2318 "%s: Got UIH for non-existing dlci=%d\n", __func__, dlci);
2319 error = ng_btsocket_rfcomm_send_command(s,RFCOMM_FRAME_DM,dlci);
2323 mtx_lock(&pcb->pcb_mtx);
2325 /* Check dlci state */
2326 if (pcb->state != NG_BTSOCKET_RFCOMM_DLC_CONNECTED) {
2327 NG_BTSOCKET_RFCOMM_WARN(
2328 "%s: Got UIH for dlci=%d in invalid state=%d, flags=%#x\n",
2329 __func__, dlci, pcb->state, pcb->flags);
2334 /* Check dlci flow control */
2335 if (((pcb->flags & NG_BTSOCKET_RFCOMM_DLC_CFC) && pcb->rx_cred <= 0) ||
2336 (pcb->lmodem & RFCOMM_MODEM_FC)) {
2337 NG_BTSOCKET_RFCOMM_ERR(
2338 "%s: Got UIH for dlci=%d with asserted flow control, state=%d, " \
2339 "flags=%#x, rx_cred=%d, lmodem=%#x\n",
2340 __func__, dlci, pcb->state, pcb->flags,
2341 pcb->rx_cred, pcb->lmodem);
2345 /* Did we get any credits? */
2346 if ((pcb->flags & NG_BTSOCKET_RFCOMM_DLC_CFC) && pf) {
2347 NG_BTSOCKET_RFCOMM_INFO(
2348 "%s: Got %d more credits for dlci=%d, state=%d, flags=%#x, " \
2349 "rx_cred=%d, tx_cred=%d\n",
2350 __func__, *mtod(m0, u_int8_t *), dlci, pcb->state,
2351 pcb->flags, pcb->rx_cred, pcb->tx_cred);
2353 pcb->tx_cred += *mtod(m0, u_int8_t *);
2356 /* Send more from the DLC. XXX check for errors? */
2357 ng_btsocket_rfcomm_pcb_send(pcb, ALOT);
2360 /* OK the of the rest of the mbuf is the data */
2361 if (m0->m_pkthdr.len > 0) {
2362 /* If we are using credit flow control decrease rx_cred here */
2363 if (pcb->flags & NG_BTSOCKET_RFCOMM_DLC_CFC) {
2364 /* Give remote peer more credits (if needed) */
2365 if (-- pcb->rx_cred <= RFCOMM_MAX_CREDITS / 2)
2366 ng_btsocket_rfcomm_send_credits(pcb);
2368 NG_BTSOCKET_RFCOMM_INFO(
2369 "%s: Remote side still has credits, dlci=%d, state=%d, flags=%#x, " \
2370 "rx_cred=%d, tx_cred=%d\n", __func__, dlci, pcb->state, pcb->flags,
2371 pcb->rx_cred, pcb->tx_cred);
2374 /* Check packet against mtu on dlci */
2375 if (m0->m_pkthdr.len > pcb->mtu) {
2376 NG_BTSOCKET_RFCOMM_ERR(
2377 "%s: Got oversized UIH for dlci=%d, state=%d, flags=%#x, mtu=%d, len=%d\n",
2378 __func__, dlci, pcb->state, pcb->flags,
2379 pcb->mtu, m0->m_pkthdr.len);
2382 } else if (m0->m_pkthdr.len > sbspace(&pcb->so->so_rcv)) {
2385 * This is really bad. Receive queue on socket does
2386 * not have enough space for the packet. We do not
2387 * have any other choice but drop the packet.
2390 NG_BTSOCKET_RFCOMM_ERR(
2391 "%s: Not enough space in socket receive queue. Dropping UIH for dlci=%d, " \
2392 "state=%d, flags=%#x, len=%d, space=%ld\n",
2393 __func__, dlci, pcb->state, pcb->flags,
2394 m0->m_pkthdr.len, sbspace(&pcb->so->so_rcv));
2398 /* Append packet to the socket receive queue */
2399 sbappend(&pcb->so->so_rcv, m0, 0);
2406 mtx_unlock(&pcb->pcb_mtx);
2408 NG_FREE_M(m0); /* checks for != NULL */
2411 } /* ng_btsocket_rfcomm_receive_uih */
2414 * Process RFCOMM MCC command (Multiplexor)
2416 * From TS 07.10 spec
2418 * "5.4.3.1 Information Data
2420 * ...The frames (UIH) sent by the initiating station have the C/R bit set
2421 * to 1 and those sent by the responding station have the C/R bit set to 0..."
2423 * "5.4.6.2 Operating procedures
2425 * Messages always exist in pairs; a command message and a corresponding
2426 * response message. If the C/R bit is set to 1 the message is a command,
2427 * if it is set to 0 the message is a response...
2431 * NOTE: Notice that when UIH frames are used to convey information on DLCI 0
2432 * there are at least two different fields that contain a C/R bit, and the
2433 * bits are set of different form. The C/R bit in the Type field shall be set
2434 * as it is stated above, while the C/R bit in the Address field (see subclause
2435 * 5.2.1.2) shall be set as it is described in subclause 5.4.3.1."
2439 ng_btsocket_rfcomm_receive_mcc(ng_btsocket_rfcomm_session_p s, struct mbuf *m0)
2441 struct rfcomm_mcc_hdr *hdr = NULL;
2442 u_int8_t cr, type, length;
2444 mtx_assert(&s->session_mtx, MA_OWNED);
2447 * We can access data directly in the first mbuf, because we have
2448 * m_pullup()'ed mbuf chain in ng_btsocket_rfcomm_receive_frame().
2449 * All MCC commands should fit into single mbuf (except probably TEST).
2452 hdr = mtod(m0, struct rfcomm_mcc_hdr *);
2453 cr = RFCOMM_CR(hdr->type);
2454 type = RFCOMM_MCC_TYPE(hdr->type);
2455 length = RFCOMM_MCC_LENGTH(hdr->length);
2457 /* Check MCC frame length */
2458 if (sizeof(*hdr) + length != m0->m_pkthdr.len) {
2459 NG_BTSOCKET_RFCOMM_ERR(
2460 "%s: Invalid MCC frame length=%d, len=%d\n",
2461 __func__, length, m0->m_pkthdr.len);
2468 case RFCOMM_MCC_TEST:
2469 return (ng_btsocket_rfcomm_receive_test(s, m0));
2472 case RFCOMM_MCC_FCON:
2473 case RFCOMM_MCC_FCOFF:
2474 return (ng_btsocket_rfcomm_receive_fc(s, m0));
2477 case RFCOMM_MCC_MSC:
2478 return (ng_btsocket_rfcomm_receive_msc(s, m0));
2481 case RFCOMM_MCC_RPN:
2482 return (ng_btsocket_rfcomm_receive_rpn(s, m0));
2485 case RFCOMM_MCC_RLS:
2486 return (ng_btsocket_rfcomm_receive_rls(s, m0));
2490 return (ng_btsocket_rfcomm_receive_pn(s, m0));
2493 case RFCOMM_MCC_NSC:
2494 NG_BTSOCKET_RFCOMM_ERR(
2495 "%s: Got MCC NSC, type=%#x, cr=%d, length=%d, session state=%d, flags=%#x, " \
2496 "mtu=%d, len=%d\n", __func__, RFCOMM_MCC_TYPE(*((u_int8_t *)(hdr + 1))), cr,
2497 length, s->state, s->flags, s->mtu, m0->m_pkthdr.len);
2502 NG_BTSOCKET_RFCOMM_ERR(
2503 "%s: Got unknown MCC, type=%#x, cr=%d, length=%d, session state=%d, " \
2504 "flags=%#x, mtu=%d, len=%d\n",
2505 __func__, type, cr, length, s->state, s->flags,
2506 s->mtu, m0->m_pkthdr.len);
2508 /* Reuse mbuf to send NSC */
2509 hdr = mtod(m0, struct rfcomm_mcc_hdr *);
2510 m0->m_pkthdr.len = m0->m_len = sizeof(*hdr);
2512 /* Create MCC NSC header */
2513 hdr->type = RFCOMM_MKMCC_TYPE(0, RFCOMM_MCC_NSC);
2514 hdr->length = RFCOMM_MKLEN8(1);
2516 /* Put back MCC command type we did not like */
2517 m0->m_data[m0->m_len] = RFCOMM_MKMCC_TYPE(cr, type);
2518 m0->m_pkthdr.len ++;
2521 /* Send UIH frame */
2522 return (ng_btsocket_rfcomm_send_uih(s,
2523 RFCOMM_MKADDRESS(INITIATOR(s), 0), 0, 0, m0));
2528 } /* ng_btsocket_rfcomm_receive_mcc */
2531 * Receive RFCOMM TEST MCC command
2535 ng_btsocket_rfcomm_receive_test(ng_btsocket_rfcomm_session_p s, struct mbuf *m0)
2537 struct rfcomm_mcc_hdr *hdr = mtod(m0, struct rfcomm_mcc_hdr *);
2540 mtx_assert(&s->session_mtx, MA_OWNED);
2542 NG_BTSOCKET_RFCOMM_INFO(
2543 "%s: Got MCC TEST, cr=%d, length=%d, session state=%d, flags=%#x, mtu=%d, " \
2544 "len=%d\n", __func__, RFCOMM_CR(hdr->type), RFCOMM_MCC_LENGTH(hdr->length),
2545 s->state, s->flags, s->mtu, m0->m_pkthdr.len);
2547 if (RFCOMM_CR(hdr->type)) {
2548 hdr->type = RFCOMM_MKMCC_TYPE(0, RFCOMM_MCC_TEST);
2549 error = ng_btsocket_rfcomm_send_uih(s,
2550 RFCOMM_MKADDRESS(INITIATOR(s), 0), 0, 0, m0);
2552 NG_FREE_M(m0); /* XXX ignore response */
2555 } /* ng_btsocket_rfcomm_receive_test */
2558 * Receive RFCOMM FCON/FCOFF MCC command
2562 ng_btsocket_rfcomm_receive_fc(ng_btsocket_rfcomm_session_p s, struct mbuf *m0)
2564 struct rfcomm_mcc_hdr *hdr = mtod(m0, struct rfcomm_mcc_hdr *);
2565 u_int8_t type = RFCOMM_MCC_TYPE(hdr->type);
2568 mtx_assert(&s->session_mtx, MA_OWNED);
2571 * Turn ON/OFF aggregate flow on the entire session. When remote peer
2572 * asserted flow control no transmission shall occur except on dlci 0
2573 * (control channel).
2576 NG_BTSOCKET_RFCOMM_INFO(
2577 "%s: Got MCC FC%s, cr=%d, length=%d, session state=%d, flags=%#x, mtu=%d, " \
2578 "len=%d\n", __func__, (type == RFCOMM_MCC_FCON)? "ON" : "OFF",
2579 RFCOMM_CR(hdr->type), RFCOMM_MCC_LENGTH(hdr->length),
2580 s->state, s->flags, s->mtu, m0->m_pkthdr.len);
2582 if (RFCOMM_CR(hdr->type)) {
2583 if (type == RFCOMM_MCC_FCON)
2584 s->flags &= ~NG_BTSOCKET_RFCOMM_SESSION_RFC;
2586 s->flags |= NG_BTSOCKET_RFCOMM_SESSION_RFC;
2588 hdr->type = RFCOMM_MKMCC_TYPE(0, type);
2589 error = ng_btsocket_rfcomm_send_uih(s,
2590 RFCOMM_MKADDRESS(INITIATOR(s), 0), 0, 0, m0);
2592 NG_FREE_M(m0); /* XXX ignore response */
2595 } /* ng_btsocket_rfcomm_receive_fc */
2598 * Receive RFCOMM MSC MCC command
2602 ng_btsocket_rfcomm_receive_msc(ng_btsocket_rfcomm_session_p s, struct mbuf *m0)
2604 struct rfcomm_mcc_hdr *hdr = mtod(m0, struct rfcomm_mcc_hdr*);
2605 struct rfcomm_mcc_msc *msc = (struct rfcomm_mcc_msc *)(hdr+1);
2606 ng_btsocket_rfcomm_pcb_t *pcb = NULL;
2609 mtx_assert(&s->session_mtx, MA_OWNED);
2611 NG_BTSOCKET_RFCOMM_INFO(
2612 "%s: Got MCC MSC, dlci=%d, cr=%d, length=%d, session state=%d, flags=%#x, " \
2614 __func__, RFCOMM_DLCI(msc->address), RFCOMM_CR(hdr->type),
2615 RFCOMM_MCC_LENGTH(hdr->length), s->state, s->flags,
2616 s->mtu, m0->m_pkthdr.len);
2618 if (RFCOMM_CR(hdr->type)) {
2619 pcb = ng_btsocket_rfcomm_pcb_by_dlci(s, RFCOMM_DLCI(msc->address));
2621 NG_BTSOCKET_RFCOMM_WARN(
2622 "%s: Got MSC command for non-existing dlci=%d\n",
2623 __func__, RFCOMM_DLCI(msc->address));
2629 mtx_lock(&pcb->pcb_mtx);
2631 if (pcb->state != NG_BTSOCKET_RFCOMM_DLC_CONNECTING &&
2632 pcb->state != NG_BTSOCKET_RFCOMM_DLC_CONNECTED) {
2633 NG_BTSOCKET_RFCOMM_WARN(
2634 "%s: Got MSC on dlci=%d in invalid state=%d\n",
2635 __func__, RFCOMM_DLCI(msc->address),
2638 mtx_unlock(&pcb->pcb_mtx);
2644 pcb->rmodem = msc->modem; /* Update remote port signals */
2646 hdr->type = RFCOMM_MKMCC_TYPE(0, RFCOMM_MCC_MSC);
2647 error = ng_btsocket_rfcomm_send_uih(s,
2648 RFCOMM_MKADDRESS(INITIATOR(s), 0), 0, 0, m0);
2651 /* Send more data from DLC. XXX check for errors? */
2652 if (!(pcb->rmodem & RFCOMM_MODEM_FC) &&
2653 !(pcb->flags & NG_BTSOCKET_RFCOMM_DLC_CFC))
2654 ng_btsocket_rfcomm_pcb_send(pcb, ALOT);
2657 mtx_unlock(&pcb->pcb_mtx);
2659 NG_FREE_M(m0); /* XXX ignore response */
2662 } /* ng_btsocket_rfcomm_receive_msc */
2665 * Receive RFCOMM RPN MCC command
2666 * XXX FIXME do we need htole16/le16toh for RPN param_mask?
2670 ng_btsocket_rfcomm_receive_rpn(ng_btsocket_rfcomm_session_p s, struct mbuf *m0)
2672 struct rfcomm_mcc_hdr *hdr = mtod(m0, struct rfcomm_mcc_hdr *);
2673 struct rfcomm_mcc_rpn *rpn = (struct rfcomm_mcc_rpn *)(hdr + 1);
2675 u_int16_t param_mask;
2676 u_int8_t bit_rate, data_bits, stop_bits, parity,
2677 flow_control, xon_char, xoff_char;
2679 mtx_assert(&s->session_mtx, MA_OWNED);
2681 NG_BTSOCKET_RFCOMM_INFO(
2682 "%s: Got MCC RPN, dlci=%d, cr=%d, length=%d, session state=%d, flags=%#x, " \
2684 __func__, RFCOMM_DLCI(rpn->dlci), RFCOMM_CR(hdr->type),
2685 RFCOMM_MCC_LENGTH(hdr->length), s->state, s->flags,
2686 s->mtu, m0->m_pkthdr.len);
2688 if (RFCOMM_CR(hdr->type)) {
2689 param_mask = RFCOMM_RPN_PM_ALL;
2691 if (RFCOMM_MCC_LENGTH(hdr->length) == 1) {
2692 /* Request - return default setting */
2693 bit_rate = RFCOMM_RPN_BR_115200;
2694 data_bits = RFCOMM_RPN_DATA_8;
2695 stop_bits = RFCOMM_RPN_STOP_1;
2696 parity = RFCOMM_RPN_PARITY_NONE;
2697 flow_control = RFCOMM_RPN_FLOW_NONE;
2698 xon_char = RFCOMM_RPN_XON_CHAR;
2699 xoff_char = RFCOMM_RPN_XOFF_CHAR;
2702 * Ignore/accept bit_rate, 8 bits, 1 stop bit, no
2703 * parity, no flow control lines, default XON/XOFF
2707 bit_rate = rpn->bit_rate;
2708 rpn->param_mask = le16toh(rpn->param_mask); /* XXX */
2710 data_bits = RFCOMM_RPN_DATA_BITS(rpn->line_settings);
2711 if (rpn->param_mask & RFCOMM_RPN_PM_DATA &&
2712 data_bits != RFCOMM_RPN_DATA_8) {
2713 data_bits = RFCOMM_RPN_DATA_8;
2714 param_mask ^= RFCOMM_RPN_PM_DATA;
2717 stop_bits = RFCOMM_RPN_STOP_BITS(rpn->line_settings);
2718 if (rpn->param_mask & RFCOMM_RPN_PM_STOP &&
2719 stop_bits != RFCOMM_RPN_STOP_1) {
2720 stop_bits = RFCOMM_RPN_STOP_1;
2721 param_mask ^= RFCOMM_RPN_PM_STOP;
2724 parity = RFCOMM_RPN_PARITY(rpn->line_settings);
2725 if (rpn->param_mask & RFCOMM_RPN_PM_PARITY &&
2726 parity != RFCOMM_RPN_PARITY_NONE) {
2727 parity = RFCOMM_RPN_PARITY_NONE;
2728 param_mask ^= RFCOMM_RPN_PM_PARITY;
2731 flow_control = rpn->flow_control;
2732 if (rpn->param_mask & RFCOMM_RPN_PM_FLOW &&
2733 flow_control != RFCOMM_RPN_FLOW_NONE) {
2734 flow_control = RFCOMM_RPN_FLOW_NONE;
2735 param_mask ^= RFCOMM_RPN_PM_FLOW;
2738 xon_char = rpn->xon_char;
2739 if (rpn->param_mask & RFCOMM_RPN_PM_XON &&
2740 xon_char != RFCOMM_RPN_XON_CHAR) {
2741 xon_char = RFCOMM_RPN_XON_CHAR;
2742 param_mask ^= RFCOMM_RPN_PM_XON;
2745 xoff_char = rpn->xoff_char;
2746 if (rpn->param_mask & RFCOMM_RPN_PM_XOFF &&
2747 xoff_char != RFCOMM_RPN_XOFF_CHAR) {
2748 xoff_char = RFCOMM_RPN_XOFF_CHAR;
2749 param_mask ^= RFCOMM_RPN_PM_XOFF;
2753 rpn->bit_rate = bit_rate;
2754 rpn->line_settings = RFCOMM_MKRPN_LINE_SETTINGS(data_bits,
2756 rpn->flow_control = flow_control;
2757 rpn->xon_char = xon_char;
2758 rpn->xoff_char = xoff_char;
2759 rpn->param_mask = htole16(param_mask); /* XXX */
2761 m0->m_pkthdr.len = m0->m_len = sizeof(*hdr) + sizeof(*rpn);
2763 hdr->type = RFCOMM_MKMCC_TYPE(0, RFCOMM_MCC_RPN);
2764 error = ng_btsocket_rfcomm_send_uih(s,
2765 RFCOMM_MKADDRESS(INITIATOR(s), 0), 0, 0, m0);
2767 NG_FREE_M(m0); /* XXX ignore response */
2770 } /* ng_btsocket_rfcomm_receive_rpn */
2773 * Receive RFCOMM RLS MCC command
2777 ng_btsocket_rfcomm_receive_rls(ng_btsocket_rfcomm_session_p s, struct mbuf *m0)
2779 struct rfcomm_mcc_hdr *hdr = mtod(m0, struct rfcomm_mcc_hdr *);
2780 struct rfcomm_mcc_rls *rls = (struct rfcomm_mcc_rls *)(hdr + 1);
2783 mtx_assert(&s->session_mtx, MA_OWNED);
2786 * XXX FIXME Do we have to do anything else here? Remote peer tries to
2787 * tell us something about DLCI. Just report what we have received and
2788 * return back received values as required by TS 07.10 spec.
2791 NG_BTSOCKET_RFCOMM_INFO(
2792 "%s: Got MCC RLS, dlci=%d, status=%#x, cr=%d, length=%d, session state=%d, " \
2793 "flags=%#x, mtu=%d, len=%d\n",
2794 __func__, RFCOMM_DLCI(rls->address), rls->status,
2795 RFCOMM_CR(hdr->type), RFCOMM_MCC_LENGTH(hdr->length),
2796 s->state, s->flags, s->mtu, m0->m_pkthdr.len);
2798 if (RFCOMM_CR(hdr->type)) {
2799 if (rls->status & 0x1)
2800 NG_BTSOCKET_RFCOMM_ERR(
2801 "%s: Got RLS dlci=%d, error=%#x\n", __func__, RFCOMM_DLCI(rls->address),
2804 hdr->type = RFCOMM_MKMCC_TYPE(0, RFCOMM_MCC_RLS);
2805 error = ng_btsocket_rfcomm_send_uih(s,
2806 RFCOMM_MKADDRESS(INITIATOR(s), 0), 0, 0, m0);
2808 NG_FREE_M(m0); /* XXX ignore responses */
2811 } /* ng_btsocket_rfcomm_receive_rls */
2814 * Receive RFCOMM PN MCC command
2818 ng_btsocket_rfcomm_receive_pn(ng_btsocket_rfcomm_session_p s, struct mbuf *m0)
2820 struct rfcomm_mcc_hdr *hdr = mtod(m0, struct rfcomm_mcc_hdr*);
2821 struct rfcomm_mcc_pn *pn = (struct rfcomm_mcc_pn *)(hdr+1);
2822 ng_btsocket_rfcomm_pcb_t *pcb = NULL;
2825 mtx_assert(&s->session_mtx, MA_OWNED);
2827 NG_BTSOCKET_RFCOMM_INFO(
2828 "%s: Got MCC PN, dlci=%d, cr=%d, length=%d, flow_control=%#x, priority=%d, " \
2829 "ack_timer=%d, mtu=%d, max_retrans=%d, credits=%d, session state=%d, " \
2830 "flags=%#x, session mtu=%d, len=%d\n",
2831 __func__, pn->dlci, RFCOMM_CR(hdr->type),
2832 RFCOMM_MCC_LENGTH(hdr->length), pn->flow_control, pn->priority,
2833 pn->ack_timer, le16toh(pn->mtu), pn->max_retrans, pn->credits,
2834 s->state, s->flags, s->mtu, m0->m_pkthdr.len);
2836 if (pn->dlci == 0) {
2837 NG_BTSOCKET_RFCOMM_ERR("%s: Zero dlci in MCC PN\n", __func__);
2843 /* Check if we have this dlci */
2844 pcb = ng_btsocket_rfcomm_pcb_by_dlci(s, pn->dlci);
2846 mtx_lock(&pcb->pcb_mtx);
2848 if (RFCOMM_CR(hdr->type)) {
2850 ng_btsocket_rfcomm_set_pn(pcb, 1, pn->flow_control,
2851 pn->credits, pn->mtu);
2853 if (pcb->flags & NG_BTSOCKET_RFCOMM_DLC_CFC) {
2854 pn->flow_control = 0xe0;
2855 pn->credits = RFCOMM_DEFAULT_CREDITS;
2857 pn->flow_control = 0;
2861 hdr->type = RFCOMM_MKMCC_TYPE(0, RFCOMM_MCC_PN);
2862 error = ng_btsocket_rfcomm_send_uih(s,
2863 RFCOMM_MKADDRESS(INITIATOR(s), 0),
2866 /* PN Response - proceed with SABM. Timeout still set */
2867 if (pcb->state == NG_BTSOCKET_RFCOMM_DLC_CONFIGURING) {
2868 ng_btsocket_rfcomm_set_pn(pcb, 0,
2869 pn->flow_control, pn->credits, pn->mtu);
2871 pcb->state = NG_BTSOCKET_RFCOMM_DLC_CONNECTING;
2872 error = ng_btsocket_rfcomm_send_command(s,
2873 RFCOMM_FRAME_SABM, pn->dlci);
2875 NG_BTSOCKET_RFCOMM_WARN(
2876 "%s: Got PN response for dlci=%d in invalid state=%d\n",
2877 __func__, pn->dlci, pcb->state);
2882 mtx_unlock(&pcb->pcb_mtx);
2883 } else if (RFCOMM_CR(hdr->type)) {
2884 /* PN request to non-existing dlci - incoming connection */
2885 pcb = ng_btsocket_rfcomm_connect_ind(s,
2886 RFCOMM_SRVCHANNEL(pn->dlci));
2888 mtx_lock(&pcb->pcb_mtx);
2890 pcb->dlci = pn->dlci;
2892 ng_btsocket_rfcomm_set_pn(pcb, 1, pn->flow_control,
2893 pn->credits, pn->mtu);
2895 if (pcb->flags & NG_BTSOCKET_RFCOMM_DLC_CFC) {
2896 pn->flow_control = 0xe0;
2897 pn->credits = RFCOMM_DEFAULT_CREDITS;
2899 pn->flow_control = 0;
2903 hdr->type = RFCOMM_MKMCC_TYPE(0, RFCOMM_MCC_PN);
2904 error = ng_btsocket_rfcomm_send_uih(s,
2905 RFCOMM_MKADDRESS(INITIATOR(s), 0),
2909 ng_btsocket_rfcomm_timeout(pcb);
2910 pcb->state = NG_BTSOCKET_RFCOMM_DLC_CONNECTING;
2911 soisconnecting(pcb->so);
2913 ng_btsocket_rfcomm_pcb_kill(pcb, error);
2915 mtx_unlock(&pcb->pcb_mtx);
2917 /* Nobody is listen()ing on this channel */
2918 error = ng_btsocket_rfcomm_send_command(s,
2919 RFCOMM_FRAME_DM, pn->dlci);
2923 NG_FREE_M(m0); /* XXX ignore response to non-existing dlci */
2926 } /* ng_btsocket_rfcomm_receive_pn */
2929 * Set PN parameters for dlci. Caller must hold pcb->pcb_mtx.
2931 * From Bluetooth spec.
2933 * "... The CL1 - CL4 field is completely redefined. (In TS07.10 this defines
2934 * the convergence layer to use, which is not applicable to RFCOMM. In RFCOMM,
2935 * in Bluetooth versions up to 1.0B, this field was forced to 0).
2937 * In the PN request sent prior to a DLC establishment, this field must contain
2938 * the value 15 (0xF), indicating support of credit based flow control in the
2939 * sender. See Table 5.3 below. If the PN response contains any other value
2940 * than 14 (0xE) in this field, it is inferred that the peer RFCOMM entity is
2941 * not supporting the credit based flow control feature. (This is only possible
2942 * if the peer RFCOMM implementation is only conforming to Bluetooth version
2943 * 1.0B.) If a PN request is sent on an already open DLC, then this field must
2944 * contain the value zero; it is not possible to set initial credits more
2945 * than once per DLC activation. A responding implementation must set this
2946 * field in the PN response to 14 (0xE), if (and only if) the value in the PN
2947 * request was 15..."
2951 ng_btsocket_rfcomm_set_pn(ng_btsocket_rfcomm_pcb_p pcb, u_int8_t cr,
2952 u_int8_t flow_control, u_int8_t credits, u_int16_t mtu)
2954 mtx_assert(&pcb->pcb_mtx, MA_OWNED);
2956 pcb->mtu = le16toh(mtu);
2959 if (flow_control == 0xf0) {
2960 pcb->flags |= NG_BTSOCKET_RFCOMM_DLC_CFC;
2961 pcb->tx_cred = credits;
2963 pcb->flags &= ~NG_BTSOCKET_RFCOMM_DLC_CFC;
2967 if (flow_control == 0xe0) {
2968 pcb->flags |= NG_BTSOCKET_RFCOMM_DLC_CFC;
2969 pcb->tx_cred = credits;
2971 pcb->flags &= ~NG_BTSOCKET_RFCOMM_DLC_CFC;
2976 NG_BTSOCKET_RFCOMM_INFO(
2977 "%s: cr=%d, dlci=%d, state=%d, flags=%#x, mtu=%d, rx_cred=%d, tx_cred=%d\n",
2978 __func__, cr, pcb->dlci, pcb->state, pcb->flags, pcb->mtu,
2979 pcb->rx_cred, pcb->tx_cred);
2980 } /* ng_btsocket_rfcomm_set_pn */
2983 * Send RFCOMM SABM/DISC/UA/DM frames. Caller must hold s->session_mtx
2987 ng_btsocket_rfcomm_send_command(ng_btsocket_rfcomm_session_p s,
2988 u_int8_t type, u_int8_t dlci)
2990 struct rfcomm_cmd_hdr *hdr = NULL;
2991 struct mbuf *m = NULL;
2994 mtx_assert(&s->session_mtx, MA_OWNED);
2996 NG_BTSOCKET_RFCOMM_INFO(
2997 "%s: Sending command type %#x, session state=%d, flags=%#x, mtu=%d, dlci=%d\n",
2998 __func__, type, s->state, s->flags, s->mtu, dlci);
3001 case RFCOMM_FRAME_SABM:
3002 case RFCOMM_FRAME_DISC:
3006 case RFCOMM_FRAME_UA:
3007 case RFCOMM_FRAME_DM:
3012 panic("%s: Invalid frame type=%#x\n", __func__, type);
3017 MGETHDR(m, M_NOWAIT, MT_DATA);
3021 m->m_pkthdr.len = m->m_len = sizeof(*hdr);
3023 hdr = mtod(m, struct rfcomm_cmd_hdr *);
3024 hdr->address = RFCOMM_MKADDRESS(cr, dlci);
3025 hdr->control = RFCOMM_MKCONTROL(type, 1);
3026 hdr->length = RFCOMM_MKLEN8(0);
3027 hdr->fcs = ng_btsocket_rfcomm_fcs3((u_int8_t *) hdr);
3029 NG_BT_MBUFQ_ENQUEUE(&s->outq, m);
3032 } /* ng_btsocket_rfcomm_send_command */
3035 * Send RFCOMM UIH frame. Caller must hold s->session_mtx
3039 ng_btsocket_rfcomm_send_uih(ng_btsocket_rfcomm_session_p s, u_int8_t address,
3040 u_int8_t pf, u_int8_t credits, struct mbuf *data)
3042 struct rfcomm_frame_hdr *hdr = NULL;
3043 struct mbuf *m = NULL, *mcrc = NULL;
3046 mtx_assert(&s->session_mtx, MA_OWNED);
3048 MGETHDR(m, M_NOWAIT, MT_DATA);
3053 m->m_pkthdr.len = m->m_len = sizeof(*hdr);
3055 MGET(mcrc, M_NOWAIT, MT_DATA);
3062 /* Fill UIH frame header */
3063 hdr = mtod(m, struct rfcomm_frame_hdr *);
3064 hdr->address = address;
3065 hdr->control = RFCOMM_MKCONTROL(RFCOMM_FRAME_UIH, pf);
3068 mcrc->m_data[0] = ng_btsocket_rfcomm_fcs2((u_int8_t *) hdr);
3070 /* Put length back */
3071 length = (data != NULL)? data->m_pkthdr.len : 0;
3073 u_int16_t l = htole16(RFCOMM_MKLEN16(length));
3075 bcopy(&l, &hdr->length, sizeof(l));
3079 hdr->length = RFCOMM_MKLEN8(length);
3082 m->m_data[m->m_len] = credits;
3090 m->m_pkthdr.len += length;
3097 NG_BTSOCKET_RFCOMM_INFO(
3098 "%s: Sending UIH state=%d, flags=%#x, address=%d, length=%d, pf=%d, " \
3099 "credits=%d, len=%d\n",
3100 __func__, s->state, s->flags, address, length, pf, credits,
3103 NG_BT_MBUFQ_ENQUEUE(&s->outq, m);
3106 } /* ng_btsocket_rfcomm_send_uih */
3109 * Send MSC request. Caller must hold pcb->pcb_mtx and pcb->session->session_mtx
3113 ng_btsocket_rfcomm_send_msc(ng_btsocket_rfcomm_pcb_p pcb)
3115 struct mbuf *m = NULL;
3116 struct rfcomm_mcc_hdr *hdr = NULL;
3117 struct rfcomm_mcc_msc *msc = NULL;
3119 mtx_assert(&pcb->session->session_mtx, MA_OWNED);
3120 mtx_assert(&pcb->pcb_mtx, MA_OWNED);
3122 MGETHDR(m, M_NOWAIT, MT_DATA);
3126 m->m_pkthdr.len = m->m_len = sizeof(*hdr) + sizeof(*msc);
3128 hdr = mtod(m, struct rfcomm_mcc_hdr *);
3129 msc = (struct rfcomm_mcc_msc *)(hdr + 1);
3131 hdr->type = RFCOMM_MKMCC_TYPE(1, RFCOMM_MCC_MSC);
3132 hdr->length = RFCOMM_MKLEN8(sizeof(*msc));
3134 msc->address = RFCOMM_MKADDRESS(1, pcb->dlci);
3135 msc->modem = pcb->lmodem;
3137 NG_BTSOCKET_RFCOMM_INFO(
3138 "%s: Sending MSC dlci=%d, state=%d, flags=%#x, address=%d, modem=%#x\n",
3139 __func__, pcb->dlci, pcb->state, pcb->flags, msc->address,
3142 return (ng_btsocket_rfcomm_send_uih(pcb->session,
3143 RFCOMM_MKADDRESS(INITIATOR(pcb->session), 0), 0, 0, m));
3144 } /* ng_btsocket_rfcomm_send_msc */
3147 * Send PN request. Caller must hold pcb->pcb_mtx and pcb->session->session_mtx
3151 ng_btsocket_rfcomm_send_pn(ng_btsocket_rfcomm_pcb_p pcb)
3153 struct mbuf *m = NULL;
3154 struct rfcomm_mcc_hdr *hdr = NULL;
3155 struct rfcomm_mcc_pn *pn = NULL;
3157 mtx_assert(&pcb->session->session_mtx, MA_OWNED);
3158 mtx_assert(&pcb->pcb_mtx, MA_OWNED);
3160 MGETHDR(m, M_NOWAIT, MT_DATA);
3164 m->m_pkthdr.len = m->m_len = sizeof(*hdr) + sizeof(*pn);
3166 hdr = mtod(m, struct rfcomm_mcc_hdr *);
3167 pn = (struct rfcomm_mcc_pn *)(hdr + 1);
3169 hdr->type = RFCOMM_MKMCC_TYPE(1, RFCOMM_MCC_PN);
3170 hdr->length = RFCOMM_MKLEN8(sizeof(*pn));
3172 pn->dlci = pcb->dlci;
3175 * Set default DLCI priority as described in GSM 07.10
3176 * (ETSI TS 101 369) clause 5.6 page 42
3179 pn->priority = (pcb->dlci < 56)? (((pcb->dlci >> 3) << 3) + 7) : 61;
3181 pn->mtu = htole16(pcb->mtu);
3182 pn->max_retrans = 0;
3184 if (pcb->flags & NG_BTSOCKET_RFCOMM_DLC_CFC) {
3185 pn->flow_control = 0xf0;
3186 pn->credits = pcb->rx_cred;
3188 pn->flow_control = 0;
3192 NG_BTSOCKET_RFCOMM_INFO(
3193 "%s: Sending PN dlci=%d, state=%d, flags=%#x, mtu=%d, flow_control=%#x, " \
3194 "credits=%d\n", __func__, pcb->dlci, pcb->state, pcb->flags, pcb->mtu,
3195 pn->flow_control, pn->credits);
3197 return (ng_btsocket_rfcomm_send_uih(pcb->session,
3198 RFCOMM_MKADDRESS(INITIATOR(pcb->session), 0), 0, 0, m));
3199 } /* ng_btsocket_rfcomm_send_pn */
3202 * Calculate and send credits based on available space in receive buffer
3206 ng_btsocket_rfcomm_send_credits(ng_btsocket_rfcomm_pcb_p pcb)
3211 mtx_assert(&pcb->pcb_mtx, MA_OWNED);
3212 mtx_assert(&pcb->session->session_mtx, MA_OWNED);
3214 NG_BTSOCKET_RFCOMM_INFO(
3215 "%s: Sending more credits, dlci=%d, state=%d, flags=%#x, mtu=%d, " \
3216 "space=%ld, tx_cred=%d, rx_cred=%d\n",
3217 __func__, pcb->dlci, pcb->state, pcb->flags, pcb->mtu,
3218 sbspace(&pcb->so->so_rcv), pcb->tx_cred, pcb->rx_cred);
3220 credits = sbspace(&pcb->so->so_rcv) / pcb->mtu;
3222 if (pcb->rx_cred + credits > RFCOMM_MAX_CREDITS)
3223 credits = RFCOMM_MAX_CREDITS - pcb->rx_cred;
3225 error = ng_btsocket_rfcomm_send_uih(
3227 RFCOMM_MKADDRESS(INITIATOR(pcb->session),
3228 pcb->dlci), 1, credits, NULL);
3230 pcb->rx_cred += credits;
3232 NG_BTSOCKET_RFCOMM_INFO(
3233 "%s: Gave remote side %d more credits, dlci=%d, state=%d, flags=%#x, " \
3234 "rx_cred=%d, tx_cred=%d\n", __func__, credits, pcb->dlci, pcb->state,
3235 pcb->flags, pcb->rx_cred, pcb->tx_cred);
3237 NG_BTSOCKET_RFCOMM_ERR(
3238 "%s: Could not send credits, error=%d, dlci=%d, state=%d, flags=%#x, " \
3239 "mtu=%d, space=%ld, tx_cred=%d, rx_cred=%d\n",
3240 __func__, error, pcb->dlci, pcb->state,
3241 pcb->flags, pcb->mtu, sbspace(&pcb->so->so_rcv),
3242 pcb->tx_cred, pcb->rx_cred);
3246 } /* ng_btsocket_rfcomm_send_credits */
3248 /*****************************************************************************
3249 *****************************************************************************
3251 *****************************************************************************
3252 *****************************************************************************/
3255 * Send data from socket send buffer
3256 * Caller must hold pcb->pcb_mtx and pcb->session->session_mtx
3260 ng_btsocket_rfcomm_pcb_send(ng_btsocket_rfcomm_pcb_p pcb, int limit)
3262 struct mbuf *m = NULL;
3263 int sent, length, error;
3265 mtx_assert(&pcb->session->session_mtx, MA_OWNED);
3266 mtx_assert(&pcb->pcb_mtx, MA_OWNED);
3268 if (pcb->flags & NG_BTSOCKET_RFCOMM_DLC_CFC)
3269 limit = min(limit, pcb->tx_cred);
3270 else if (!(pcb->rmodem & RFCOMM_MODEM_FC))
3271 limit = min(limit, RFCOMM_MAX_CREDITS); /* XXX ??? */
3276 NG_BTSOCKET_RFCOMM_INFO(
3277 "%s: Could not send - remote flow control asserted, dlci=%d, flags=%#x, " \
3278 "rmodem=%#x, tx_cred=%d\n",
3279 __func__, pcb->dlci, pcb->flags, pcb->rmodem,
3285 for (error = 0, sent = 0; sent < limit; sent ++) {
3286 length = min(pcb->mtu, sbavail(&pcb->so->so_snd));
3290 /* Get the chunk from the socket's send buffer */
3291 m = ng_btsocket_rfcomm_prepare_packet(&pcb->so->so_snd, length);
3297 sbdrop(&pcb->so->so_snd, length);
3299 error = ng_btsocket_rfcomm_send_uih(pcb->session,
3300 RFCOMM_MKADDRESS(INITIATOR(pcb->session),
3301 pcb->dlci), 0, 0, m);
3306 if (pcb->flags & NG_BTSOCKET_RFCOMM_DLC_CFC)
3307 pcb->tx_cred -= sent;
3309 if (error == 0 && sent > 0) {
3310 pcb->flags &= ~NG_BTSOCKET_RFCOMM_DLC_SENDING;
3315 } /* ng_btsocket_rfcomm_pcb_send */
3318 * Unlink and disconnect DLC. If ng_btsocket_rfcomm_pcb_kill() returns
3319 * non zero value than socket has no reference and has to be detached.
3320 * Caller must hold pcb->pcb_mtx and pcb->session->session_mtx
3324 ng_btsocket_rfcomm_pcb_kill(ng_btsocket_rfcomm_pcb_p pcb, int error)
3326 ng_btsocket_rfcomm_session_p s = pcb->session;
3328 NG_BTSOCKET_RFCOMM_INFO(
3329 "%s: Killing DLC, so=%p, dlci=%d, state=%d, flags=%#x, error=%d\n",
3330 __func__, pcb->so, pcb->dlci, pcb->state, pcb->flags, error);
3332 if (pcb->session == NULL)
3333 panic("%s: DLC without session, pcb=%p, state=%d, flags=%#x\n",
3334 __func__, pcb, pcb->state, pcb->flags);
3336 mtx_assert(&pcb->session->session_mtx, MA_OWNED);
3337 mtx_assert(&pcb->pcb_mtx, MA_OWNED);
3339 if (pcb->flags & NG_BTSOCKET_RFCOMM_DLC_TIMO)
3340 ng_btsocket_rfcomm_untimeout(pcb);
3342 /* Detach DLC from the session. Does not matter which state DLC in */
3343 LIST_REMOVE(pcb, session_next);
3344 pcb->session = NULL;
3346 /* Change DLC state and wakeup all sleepers */
3347 pcb->state = NG_BTSOCKET_RFCOMM_DLC_CLOSED;
3348 pcb->so->so_error = error;
3349 soisdisconnected(pcb->so);
3350 wakeup(&pcb->state);
3352 /* Check if we have any DLCs left on the session */
3353 if (LIST_EMPTY(&s->dlcs) && INITIATOR(s)) {
3354 NG_BTSOCKET_RFCOMM_INFO(
3355 "%s: Disconnecting session, state=%d, flags=%#x, mtu=%d\n",
3356 __func__, s->state, s->flags, s->mtu);
3359 case NG_BTSOCKET_RFCOMM_SESSION_CLOSED:
3360 case NG_BTSOCKET_RFCOMM_SESSION_DISCONNECTING:
3362 * Do not have to do anything here. We can get here
3363 * when L2CAP connection was terminated or we have
3364 * received DISC on multiplexor channel
3368 case NG_BTSOCKET_RFCOMM_SESSION_OPEN:
3369 /* Send DISC on multiplexor channel */
3370 error = ng_btsocket_rfcomm_send_command(s,
3371 RFCOMM_FRAME_DISC, 0);
3373 s->state = NG_BTSOCKET_RFCOMM_SESSION_DISCONNECTING;
3378 case NG_BTSOCKET_RFCOMM_SESSION_CONNECTING:
3379 case NG_BTSOCKET_RFCOMM_SESSION_CONNECTED:
3380 s->state = NG_BTSOCKET_RFCOMM_SESSION_CLOSED;
3383 /* case NG_BTSOCKET_RFCOMM_SESSION_LISTENING: */
3385 panic("%s: Invalid session state=%d, flags=%#x\n",
3386 __func__, s->state, s->flags);
3390 ng_btsocket_rfcomm_task_wakeup();
3392 } /* ng_btsocket_rfcomm_pcb_kill */
3395 * Look for given dlci for given RFCOMM session. Caller must hold s->session_mtx
3398 static ng_btsocket_rfcomm_pcb_p
3399 ng_btsocket_rfcomm_pcb_by_dlci(ng_btsocket_rfcomm_session_p s, int dlci)
3401 ng_btsocket_rfcomm_pcb_p pcb = NULL;
3403 mtx_assert(&s->session_mtx, MA_OWNED);
3405 LIST_FOREACH(pcb, &s->dlcs, session_next)
3406 if (pcb->dlci == dlci)
3410 } /* ng_btsocket_rfcomm_pcb_by_dlci */
3413 * Look for socket that listens on given src address and given channel
3416 static ng_btsocket_rfcomm_pcb_p
3417 ng_btsocket_rfcomm_pcb_listener(bdaddr_p src, int channel)
3419 ng_btsocket_rfcomm_pcb_p pcb = NULL, pcb1 = NULL;
3421 mtx_lock(&ng_btsocket_rfcomm_sockets_mtx);
3423 LIST_FOREACH(pcb, &ng_btsocket_rfcomm_sockets, next) {
3424 if (pcb->channel != channel ||
3425 !(pcb->so->so_options & SO_ACCEPTCONN))
3428 if (bcmp(&pcb->src, src, sizeof(*src)) == 0)
3431 if (bcmp(&pcb->src, NG_HCI_BDADDR_ANY, sizeof(bdaddr_t)) == 0)
3435 mtx_unlock(&ng_btsocket_rfcomm_sockets_mtx);
3437 return ((pcb != NULL)? pcb : pcb1);
3438 } /* ng_btsocket_rfcomm_pcb_listener */
3440 /*****************************************************************************
3441 *****************************************************************************
3443 *****************************************************************************
3444 *****************************************************************************/
3447 * Set timeout. Caller MUST hold pcb_mtx
3451 ng_btsocket_rfcomm_timeout(ng_btsocket_rfcomm_pcb_p pcb)
3453 mtx_assert(&pcb->pcb_mtx, MA_OWNED);
3455 if (!(pcb->flags & NG_BTSOCKET_RFCOMM_DLC_TIMO)) {
3456 pcb->flags |= NG_BTSOCKET_RFCOMM_DLC_TIMO;
3457 pcb->flags &= ~NG_BTSOCKET_RFCOMM_DLC_TIMEDOUT;
3458 callout_reset(&pcb->timo, ng_btsocket_rfcomm_timo * hz,
3459 ng_btsocket_rfcomm_process_timeout, pcb);
3461 panic("%s: Duplicated socket timeout?!\n", __func__);
3462 } /* ng_btsocket_rfcomm_timeout */
3465 * Unset pcb timeout. Caller MUST hold pcb_mtx
3469 ng_btsocket_rfcomm_untimeout(ng_btsocket_rfcomm_pcb_p pcb)
3471 mtx_assert(&pcb->pcb_mtx, MA_OWNED);
3473 if (pcb->flags & NG_BTSOCKET_RFCOMM_DLC_TIMO) {
3474 callout_stop(&pcb->timo);
3475 pcb->flags &= ~NG_BTSOCKET_RFCOMM_DLC_TIMO;
3476 pcb->flags &= ~NG_BTSOCKET_RFCOMM_DLC_TIMEDOUT;
3478 panic("%s: No socket timeout?!\n", __func__);
3479 } /* ng_btsocket_rfcomm_timeout */
3482 * Process pcb timeout
3486 ng_btsocket_rfcomm_process_timeout(void *xpcb)
3488 ng_btsocket_rfcomm_pcb_p pcb = (ng_btsocket_rfcomm_pcb_p) xpcb;
3490 mtx_assert(&pcb->pcb_mtx, MA_OWNED);
3492 NG_BTSOCKET_RFCOMM_INFO(
3493 "%s: Timeout, so=%p, dlci=%d, state=%d, flags=%#x\n",
3494 __func__, pcb->so, pcb->dlci, pcb->state, pcb->flags);
3496 pcb->flags &= ~NG_BTSOCKET_RFCOMM_DLC_TIMO;
3497 pcb->flags |= NG_BTSOCKET_RFCOMM_DLC_TIMEDOUT;
3499 switch (pcb->state) {
3500 case NG_BTSOCKET_RFCOMM_DLC_CONFIGURING:
3501 case NG_BTSOCKET_RFCOMM_DLC_CONNECTING:
3502 pcb->state = NG_BTSOCKET_RFCOMM_DLC_DISCONNECTING;
3505 case NG_BTSOCKET_RFCOMM_DLC_W4_CONNECT:
3506 case NG_BTSOCKET_RFCOMM_DLC_DISCONNECTING:
3511 "%s: DLC timeout in invalid state, dlci=%d, state=%d, flags=%#x\n",
3512 __func__, pcb->dlci, pcb->state, pcb->flags);
3516 ng_btsocket_rfcomm_task_wakeup();
3517 } /* ng_btsocket_rfcomm_process_timeout */
3520 * Get up to length bytes from the socket buffer
3523 static struct mbuf *
3524 ng_btsocket_rfcomm_prepare_packet(struct sockbuf *sb, int length)
3526 struct mbuf *top = NULL, *m = NULL, *n = NULL, *nextpkt = NULL;
3527 int mlen, noff, len;
3529 MGETHDR(top, M_NOWAIT, MT_DATA);
3533 top->m_pkthdr.len = length;
3539 nextpkt = n->m_nextpkt;
3542 while (length > 0 && n != NULL) {
3543 len = min(mlen - m->m_len, n->m_len - noff);
3547 bcopy(mtod(n, caddr_t)+noff, mtod(m, caddr_t)+m->m_len, len);
3552 if (length > 0 && m->m_len == mlen) {
3553 MGET(m->m_next, M_NOWAIT, MT_DATA);
3554 if (m->m_next == NULL) {
3564 if (noff == n->m_len) {
3571 nextpkt = (n != NULL)? n->m_nextpkt : NULL;
3576 panic("%s: length=%d\n", __func__, length);
3577 if (length > 0 && n == NULL)
3578 panic("%s: bogus length=%d, n=%p\n", __func__, length, n);
3581 } /* ng_btsocket_rfcomm_prepare_packet */