Vendor import of netgraph from FreeBSD-current 20080626
[dragonfly.git] / sys / netgraph7 / bluetooth / socket / ng_btsocket_rfcomm.c
blob3eaeccf524010e1d692ccb74c78fc3a3f1ac3f7c
1 /*
2 * ng_btsocket_rfcomm.c
3 */
5 /*-
6 * Copyright (c) 2001-2003 Maksim Yevmenkin <m_evmenkin@yahoo.com>
7 * All rights reserved.
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
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
28 * SUCH DAMAGE.
30 * $Id: ng_btsocket_rfcomm.c,v 1.28 2003/09/14 23:29:06 max Exp $
31 * $FreeBSD: src/sys/netgraph/bluetooth/socket/ng_btsocket_rfcomm.c,v 1.27 2007/10/29 19:06:47 emax 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>
43 #include <sys/lock.h>
44 #include <sys/malloc.h>
45 #include <sys/mbuf.h>
46 #include <sys/mutex.h>
47 #include <sys/proc.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>
54 #include <sys/uio.h>
55 #include <netgraph/ng_message.h>
56 #include <netgraph/netgraph.h>
57 #include <netgraph/bluetooth/include/ng_bluetooth.h>
58 #include <netgraph/bluetooth/include/ng_hci.h>
59 #include <netgraph/bluetooth/include/ng_l2cap.h>
60 #include <netgraph/bluetooth/include/ng_btsocket.h>
61 #include <netgraph/bluetooth/include/ng_btsocket_l2cap.h>
62 #include <netgraph/bluetooth/include/ng_btsocket_rfcomm.h>
64 /* MALLOC define */
65 #ifdef NG_SEPARATE_MALLOC
66 MALLOC_DEFINE(M_NETGRAPH_BTSOCKET_RFCOMM, "netgraph_btsocks_rfcomm",
67 "Netgraph Bluetooth RFCOMM sockets");
68 #else
69 #define M_NETGRAPH_BTSOCKET_RFCOMM M_NETGRAPH
70 #endif /* NG_SEPARATE_MALLOC */
72 /* Debug */
73 #define NG_BTSOCKET_RFCOMM_INFO \
74 if (ng_btsocket_rfcomm_debug_level >= NG_BTSOCKET_INFO_LEVEL) \
75 printf
77 #define NG_BTSOCKET_RFCOMM_WARN \
78 if (ng_btsocket_rfcomm_debug_level >= NG_BTSOCKET_WARN_LEVEL) \
79 printf
81 #define NG_BTSOCKET_RFCOMM_ERR \
82 if (ng_btsocket_rfcomm_debug_level >= NG_BTSOCKET_ERR_LEVEL) \
83 printf
85 #define NG_BTSOCKET_RFCOMM_ALERT \
86 if (ng_btsocket_rfcomm_debug_level >= NG_BTSOCKET_ALERT_LEVEL) \
87 printf
89 #define ALOT 0x7fff
91 /* Local prototypes */
92 static void ng_btsocket_rfcomm_upcall
93 (struct socket *so, void *arg, int waitflag);
94 static void ng_btsocket_rfcomm_sessions_task
95 (void *ctx, int pending);
96 static void ng_btsocket_rfcomm_session_task
97 (ng_btsocket_rfcomm_session_p s);
98 #define ng_btsocket_rfcomm_task_wakeup() \
99 taskqueue_enqueue(taskqueue_swi_giant, &ng_btsocket_rfcomm_task)
101 static ng_btsocket_rfcomm_pcb_p ng_btsocket_rfcomm_connect_ind
102 (ng_btsocket_rfcomm_session_p s, int channel);
103 static void ng_btsocket_rfcomm_connect_cfm
104 (ng_btsocket_rfcomm_session_p s);
106 static int ng_btsocket_rfcomm_session_create
107 (ng_btsocket_rfcomm_session_p *sp, struct socket *l2so,
108 bdaddr_p src, bdaddr_p dst, struct thread *td);
109 static int ng_btsocket_rfcomm_session_accept
110 (ng_btsocket_rfcomm_session_p s0);
111 static int ng_btsocket_rfcomm_session_connect
112 (ng_btsocket_rfcomm_session_p s);
113 static int ng_btsocket_rfcomm_session_receive
114 (ng_btsocket_rfcomm_session_p s);
115 static int ng_btsocket_rfcomm_session_send
116 (ng_btsocket_rfcomm_session_p s);
117 static void ng_btsocket_rfcomm_session_clean
118 (ng_btsocket_rfcomm_session_p s);
119 static void ng_btsocket_rfcomm_session_process_pcb
120 (ng_btsocket_rfcomm_session_p s);
121 static ng_btsocket_rfcomm_session_p ng_btsocket_rfcomm_session_by_addr
122 (bdaddr_p src, bdaddr_p dst);
124 static int ng_btsocket_rfcomm_receive_frame
125 (ng_btsocket_rfcomm_session_p s, struct mbuf *m0);
126 static int ng_btsocket_rfcomm_receive_sabm
127 (ng_btsocket_rfcomm_session_p s, int dlci);
128 static int ng_btsocket_rfcomm_receive_disc
129 (ng_btsocket_rfcomm_session_p s, int dlci);
130 static int ng_btsocket_rfcomm_receive_ua
131 (ng_btsocket_rfcomm_session_p s, int dlci);
132 static int ng_btsocket_rfcomm_receive_dm
133 (ng_btsocket_rfcomm_session_p s, int dlci);
134 static int ng_btsocket_rfcomm_receive_uih
135 (ng_btsocket_rfcomm_session_p s, int dlci, int pf, struct mbuf *m0);
136 static int ng_btsocket_rfcomm_receive_mcc
137 (ng_btsocket_rfcomm_session_p s, struct mbuf *m0);
138 static int ng_btsocket_rfcomm_receive_test
139 (ng_btsocket_rfcomm_session_p s, struct mbuf *m0);
140 static int ng_btsocket_rfcomm_receive_fc
141 (ng_btsocket_rfcomm_session_p s, struct mbuf *m0);
142 static int ng_btsocket_rfcomm_receive_msc
143 (ng_btsocket_rfcomm_session_p s, struct mbuf *m0);
144 static int ng_btsocket_rfcomm_receive_rpn
145 (ng_btsocket_rfcomm_session_p s, struct mbuf *m0);
146 static int ng_btsocket_rfcomm_receive_rls
147 (ng_btsocket_rfcomm_session_p s, struct mbuf *m0);
148 static int ng_btsocket_rfcomm_receive_pn
149 (ng_btsocket_rfcomm_session_p s, struct mbuf *m0);
150 static void ng_btsocket_rfcomm_set_pn
151 (ng_btsocket_rfcomm_pcb_p pcb, u_int8_t cr, u_int8_t flow_control,
152 u_int8_t credits, u_int16_t mtu);
154 static int ng_btsocket_rfcomm_send_command
155 (ng_btsocket_rfcomm_session_p s, u_int8_t type, u_int8_t dlci);
156 static int ng_btsocket_rfcomm_send_uih
157 (ng_btsocket_rfcomm_session_p s, u_int8_t address, u_int8_t pf,
158 u_int8_t credits, struct mbuf *data);
159 static int ng_btsocket_rfcomm_send_msc
160 (ng_btsocket_rfcomm_pcb_p pcb);
161 static int ng_btsocket_rfcomm_send_pn
162 (ng_btsocket_rfcomm_pcb_p pcb);
163 static int ng_btsocket_rfcomm_send_credits
164 (ng_btsocket_rfcomm_pcb_p pcb);
166 static int ng_btsocket_rfcomm_pcb_send
167 (ng_btsocket_rfcomm_pcb_p pcb, int limit);
168 static void ng_btsocket_rfcomm_pcb_kill
169 (ng_btsocket_rfcomm_pcb_p pcb, int error);
170 static ng_btsocket_rfcomm_pcb_p ng_btsocket_rfcomm_pcb_by_dlci
171 (ng_btsocket_rfcomm_session_p s, int dlci);
172 static ng_btsocket_rfcomm_pcb_p ng_btsocket_rfcomm_pcb_listener
173 (bdaddr_p src, int channel);
175 static void ng_btsocket_rfcomm_timeout
176 (ng_btsocket_rfcomm_pcb_p pcb);
177 static void ng_btsocket_rfcomm_untimeout
178 (ng_btsocket_rfcomm_pcb_p pcb);
179 static void ng_btsocket_rfcomm_process_timeout
180 (void *xpcb);
182 static struct mbuf * ng_btsocket_rfcomm_prepare_packet
183 (struct sockbuf *sb, int length);
185 /* Globals */
186 extern int ifqmaxlen;
187 static u_int32_t ng_btsocket_rfcomm_debug_level;
188 static u_int32_t ng_btsocket_rfcomm_timo;
189 struct task ng_btsocket_rfcomm_task;
190 static LIST_HEAD(, ng_btsocket_rfcomm_session) ng_btsocket_rfcomm_sessions;
191 static struct mtx ng_btsocket_rfcomm_sessions_mtx;
192 static LIST_HEAD(, ng_btsocket_rfcomm_pcb) ng_btsocket_rfcomm_sockets;
193 static struct mtx ng_btsocket_rfcomm_sockets_mtx;
195 /* Sysctl tree */
196 SYSCTL_DECL(_net_bluetooth_rfcomm_sockets);
197 SYSCTL_NODE(_net_bluetooth_rfcomm_sockets, OID_AUTO, stream, CTLFLAG_RW,
198 0, "Bluetooth STREAM RFCOMM sockets family");
199 SYSCTL_INT(_net_bluetooth_rfcomm_sockets_stream, OID_AUTO, debug_level,
200 CTLFLAG_RW,
201 &ng_btsocket_rfcomm_debug_level, NG_BTSOCKET_INFO_LEVEL,
202 "Bluetooth STREAM RFCOMM sockets debug level");
203 SYSCTL_INT(_net_bluetooth_rfcomm_sockets_stream, OID_AUTO, timeout,
204 CTLFLAG_RW,
205 &ng_btsocket_rfcomm_timo, 60,
206 "Bluetooth STREAM RFCOMM sockets timeout");
208 /*****************************************************************************
209 *****************************************************************************
210 ** RFCOMM CRC
211 *****************************************************************************
212 *****************************************************************************/
214 static u_int8_t ng_btsocket_rfcomm_crc_table[256] = {
215 0x00, 0x91, 0xe3, 0x72, 0x07, 0x96, 0xe4, 0x75,
216 0x0e, 0x9f, 0xed, 0x7c, 0x09, 0x98, 0xea, 0x7b,
217 0x1c, 0x8d, 0xff, 0x6e, 0x1b, 0x8a, 0xf8, 0x69,
218 0x12, 0x83, 0xf1, 0x60, 0x15, 0x84, 0xf6, 0x67,
220 0x38, 0xa9, 0xdb, 0x4a, 0x3f, 0xae, 0xdc, 0x4d,
221 0x36, 0xa7, 0xd5, 0x44, 0x31, 0xa0, 0xd2, 0x43,
222 0x24, 0xb5, 0xc7, 0x56, 0x23, 0xb2, 0xc0, 0x51,
223 0x2a, 0xbb, 0xc9, 0x58, 0x2d, 0xbc, 0xce, 0x5f,
225 0x70, 0xe1, 0x93, 0x02, 0x77, 0xe6, 0x94, 0x05,
226 0x7e, 0xef, 0x9d, 0x0c, 0x79, 0xe8, 0x9a, 0x0b,
227 0x6c, 0xfd, 0x8f, 0x1e, 0x6b, 0xfa, 0x88, 0x19,
228 0x62, 0xf3, 0x81, 0x10, 0x65, 0xf4, 0x86, 0x17,
230 0x48, 0xd9, 0xab, 0x3a, 0x4f, 0xde, 0xac, 0x3d,
231 0x46, 0xd7, 0xa5, 0x34, 0x41, 0xd0, 0xa2, 0x33,
232 0x54, 0xc5, 0xb7, 0x26, 0x53, 0xc2, 0xb0, 0x21,
233 0x5a, 0xcb, 0xb9, 0x28, 0x5d, 0xcc, 0xbe, 0x2f,
235 0xe0, 0x71, 0x03, 0x92, 0xe7, 0x76, 0x04, 0x95,
236 0xee, 0x7f, 0x0d, 0x9c, 0xe9, 0x78, 0x0a, 0x9b,
237 0xfc, 0x6d, 0x1f, 0x8e, 0xfb, 0x6a, 0x18, 0x89,
238 0xf2, 0x63, 0x11, 0x80, 0xf5, 0x64, 0x16, 0x87,
240 0xd8, 0x49, 0x3b, 0xaa, 0xdf, 0x4e, 0x3c, 0xad,
241 0xd6, 0x47, 0x35, 0xa4, 0xd1, 0x40, 0x32, 0xa3,
242 0xc4, 0x55, 0x27, 0xb6, 0xc3, 0x52, 0x20, 0xb1,
243 0xca, 0x5b, 0x29, 0xb8, 0xcd, 0x5c, 0x2e, 0xbf,
245 0x90, 0x01, 0x73, 0xe2, 0x97, 0x06, 0x74, 0xe5,
246 0x9e, 0x0f, 0x7d, 0xec, 0x99, 0x08, 0x7a, 0xeb,
247 0x8c, 0x1d, 0x6f, 0xfe, 0x8b, 0x1a, 0x68, 0xf9,
248 0x82, 0x13, 0x61, 0xf0, 0x85, 0x14, 0x66, 0xf7,
250 0xa8, 0x39, 0x4b, 0xda, 0xaf, 0x3e, 0x4c, 0xdd,
251 0xa6, 0x37, 0x45, 0xd4, 0xa1, 0x30, 0x42, 0xd3,
252 0xb4, 0x25, 0x57, 0xc6, 0xb3, 0x22, 0x50, 0xc1,
253 0xba, 0x2b, 0x59, 0xc8, 0xbd, 0x2c, 0x5e, 0xcf
256 /* CRC */
257 static u_int8_t
258 ng_btsocket_rfcomm_crc(u_int8_t *data, int length)
260 u_int8_t crc = 0xff;
262 while (length --)
263 crc = ng_btsocket_rfcomm_crc_table[crc ^ *data++];
265 return (crc);
266 } /* ng_btsocket_rfcomm_crc */
268 /* FCS on 2 bytes */
269 static u_int8_t
270 ng_btsocket_rfcomm_fcs2(u_int8_t *data)
272 return (0xff - ng_btsocket_rfcomm_crc(data, 2));
273 } /* ng_btsocket_rfcomm_fcs2 */
275 /* FCS on 3 bytes */
276 static u_int8_t
277 ng_btsocket_rfcomm_fcs3(u_int8_t *data)
279 return (0xff - ng_btsocket_rfcomm_crc(data, 3));
280 } /* ng_btsocket_rfcomm_fcs3 */
283 * Check FCS
285 * From Bluetooth spec
287 * "... In 07.10, the frame check sequence (FCS) is calculated on different
288 * sets of fields for different frame types. These are the fields that the
289 * FCS are calculated on:
291 * For SABM, DISC, UA, DM frames: on Address, Control and length field.
292 * For UIH frames: on Address and Control field.
294 * (This is stated here for clarification, and to set the standard for RFCOMM;
295 * the fields included in FCS calculation have actually changed in version
296 * 7.0.0 of TS 07.10, but RFCOMM will not change the FCS calculation scheme
297 * from the one above.) ..."
300 static int
301 ng_btsocket_rfcomm_check_fcs(u_int8_t *data, int type, u_int8_t fcs)
303 if (type != RFCOMM_FRAME_UIH)
304 return (ng_btsocket_rfcomm_fcs3(data) != fcs);
306 return (ng_btsocket_rfcomm_fcs2(data) != fcs);
307 } /* ng_btsocket_rfcomm_check_fcs */
309 /*****************************************************************************
310 *****************************************************************************
311 ** Socket interface
312 *****************************************************************************
313 *****************************************************************************/
316 * Initialize everything
319 void
320 ng_btsocket_rfcomm_init(void)
322 ng_btsocket_rfcomm_debug_level = NG_BTSOCKET_WARN_LEVEL;
323 ng_btsocket_rfcomm_timo = 60;
325 /* RFCOMM task */
326 TASK_INIT(&ng_btsocket_rfcomm_task, 0,
327 ng_btsocket_rfcomm_sessions_task, NULL);
329 /* RFCOMM sessions list */
330 LIST_INIT(&ng_btsocket_rfcomm_sessions);
331 mtx_init(&ng_btsocket_rfcomm_sessions_mtx,
332 "btsocks_rfcomm_sessions_mtx", NULL, MTX_DEF);
334 /* RFCOMM sockets list */
335 LIST_INIT(&ng_btsocket_rfcomm_sockets);
336 mtx_init(&ng_btsocket_rfcomm_sockets_mtx,
337 "btsocks_rfcomm_sockets_mtx", NULL, MTX_DEF);
338 } /* ng_btsocket_rfcomm_init */
341 * Abort connection on socket
344 void
345 ng_btsocket_rfcomm_abort(struct socket *so)
348 so->so_error = ECONNABORTED;
349 (void)ng_btsocket_rfcomm_disconnect(so);
350 } /* ng_btsocket_rfcomm_abort */
352 void
353 ng_btsocket_rfcomm_close(struct socket *so)
356 (void)ng_btsocket_rfcomm_disconnect(so);
357 } /* ng_btsocket_rfcomm_close */
360 * Accept connection on socket. Nothing to do here, socket must be connected
361 * and ready, so just return peer address and be done with it.
365 ng_btsocket_rfcomm_accept(struct socket *so, struct sockaddr **nam)
367 return (ng_btsocket_rfcomm_peeraddr(so, nam));
368 } /* ng_btsocket_rfcomm_accept */
371 * Create and attach new socket
375 ng_btsocket_rfcomm_attach(struct socket *so, int proto, struct thread *td)
377 ng_btsocket_rfcomm_pcb_p pcb = so2rfcomm_pcb(so);
378 int error;
380 /* Check socket and protocol */
381 if (so->so_type != SOCK_STREAM)
382 return (ESOCKTNOSUPPORT);
384 #if 0 /* XXX sonewconn() calls "pru_attach" with proto == 0 */
385 if (proto != 0)
386 if (proto != BLUETOOTH_PROTO_RFCOMM)
387 return (EPROTONOSUPPORT);
388 #endif /* XXX */
390 if (pcb != NULL)
391 return (EISCONN);
393 /* Reserve send and receive space if it is not reserved yet */
394 if ((so->so_snd.sb_hiwat == 0) || (so->so_rcv.sb_hiwat == 0)) {
395 error = soreserve(so, NG_BTSOCKET_RFCOMM_SENDSPACE,
396 NG_BTSOCKET_RFCOMM_RECVSPACE);
397 if (error != 0)
398 return (error);
401 /* Allocate the PCB */
402 MALLOC(pcb, ng_btsocket_rfcomm_pcb_p, sizeof(*pcb),
403 M_NETGRAPH_BTSOCKET_RFCOMM, M_NOWAIT | M_ZERO);
404 if (pcb == NULL)
405 return (ENOMEM);
407 /* Link the PCB and the socket */
408 so->so_pcb = (caddr_t) pcb;
409 pcb->so = so;
411 /* Initialize PCB */
412 pcb->state = NG_BTSOCKET_RFCOMM_DLC_CLOSED;
413 pcb->flags = NG_BTSOCKET_RFCOMM_DLC_CFC;
415 pcb->lmodem =
416 pcb->rmodem = (RFCOMM_MODEM_RTC | RFCOMM_MODEM_RTR | RFCOMM_MODEM_DV);
418 pcb->mtu = RFCOMM_DEFAULT_MTU;
419 pcb->tx_cred = 0;
420 pcb->rx_cred = RFCOMM_DEFAULT_CREDITS;
422 mtx_init(&pcb->pcb_mtx, "btsocks_rfcomm_pcb_mtx", NULL, MTX_DEF);
423 callout_handle_init(&pcb->timo);
425 /* Add the PCB to the list */
426 mtx_lock(&ng_btsocket_rfcomm_sockets_mtx);
427 LIST_INSERT_HEAD(&ng_btsocket_rfcomm_sockets, pcb, next);
428 mtx_unlock(&ng_btsocket_rfcomm_sockets_mtx);
430 return (0);
431 } /* ng_btsocket_rfcomm_attach */
434 * Bind socket
438 ng_btsocket_rfcomm_bind(struct socket *so, struct sockaddr *nam,
439 struct thread *td)
441 ng_btsocket_rfcomm_pcb_t *pcb = so2rfcomm_pcb(so), *pcb1;
442 struct sockaddr_rfcomm *sa = (struct sockaddr_rfcomm *) nam;
444 if (pcb == NULL)
445 return (EINVAL);
447 /* Verify address */
448 if (sa == NULL)
449 return (EINVAL);
450 if (sa->rfcomm_family != AF_BLUETOOTH)
451 return (EAFNOSUPPORT);
452 if (sa->rfcomm_len != sizeof(*sa))
453 return (EINVAL);
454 if (sa->rfcomm_channel > 30)
455 return (EINVAL);
457 mtx_lock(&pcb->pcb_mtx);
459 if (sa->rfcomm_channel != 0) {
460 mtx_lock(&ng_btsocket_rfcomm_sockets_mtx);
462 LIST_FOREACH(pcb1, &ng_btsocket_rfcomm_sockets, next) {
463 if (pcb1->channel == sa->rfcomm_channel &&
464 bcmp(&pcb1->src, &sa->rfcomm_bdaddr,
465 sizeof(pcb1->src)) == 0) {
466 mtx_unlock(&ng_btsocket_rfcomm_sockets_mtx);
467 mtx_unlock(&pcb->pcb_mtx);
469 return (EADDRINUSE);
473 mtx_unlock(&ng_btsocket_rfcomm_sockets_mtx);
476 bcopy(&sa->rfcomm_bdaddr, &pcb->src, sizeof(pcb->src));
477 pcb->channel = sa->rfcomm_channel;
479 mtx_unlock(&pcb->pcb_mtx);
481 return (0);
482 } /* ng_btsocket_rfcomm_bind */
485 * Connect socket
489 ng_btsocket_rfcomm_connect(struct socket *so, struct sockaddr *nam,
490 struct thread *td)
492 ng_btsocket_rfcomm_pcb_t *pcb = so2rfcomm_pcb(so);
493 struct sockaddr_rfcomm *sa = (struct sockaddr_rfcomm *) nam;
494 ng_btsocket_rfcomm_session_t *s = NULL;
495 struct socket *l2so = NULL;
496 int dlci, error = 0;
498 if (pcb == NULL)
499 return (EINVAL);
501 /* Verify address */
502 if (sa == NULL)
503 return (EINVAL);
504 if (sa->rfcomm_family != AF_BLUETOOTH)
505 return (EAFNOSUPPORT);
506 if (sa->rfcomm_len != sizeof(*sa))
507 return (EINVAL);
508 if (sa->rfcomm_channel > 30)
509 return (EINVAL);
510 if (sa->rfcomm_channel == 0 ||
511 bcmp(&sa->rfcomm_bdaddr, NG_HCI_BDADDR_ANY, sizeof(bdaddr_t)) == 0)
512 return (EDESTADDRREQ);
515 * XXX FIXME - This is FUBAR. socreate() will call soalloc(1), i.e.
516 * soalloc() is allowed to sleep in MALLOC. This creates "could sleep"
517 * WITNESS warnings. To work around this problem we will create L2CAP
518 * socket first and then check if we actually need it. Note that we
519 * will not check for errors in socreate() because if we failed to
520 * create L2CAP socket at this point we still might have already open
521 * session.
524 error = socreate(PF_BLUETOOTH, &l2so, SOCK_SEQPACKET,
525 BLUETOOTH_PROTO_L2CAP, td->td_ucred, td);
528 * Look for session between "pcb->src" and "sa->rfcomm_bdaddr" (dst)
531 mtx_lock(&ng_btsocket_rfcomm_sessions_mtx);
533 s = ng_btsocket_rfcomm_session_by_addr(&pcb->src, &sa->rfcomm_bdaddr);
534 if (s == NULL) {
536 * We need to create new RFCOMM session. Check if we have L2CAP
537 * socket. If l2so == NULL then error has the error code from
538 * socreate()
541 if (l2so == NULL) {
542 mtx_unlock(&ng_btsocket_rfcomm_sessions_mtx);
543 return (error);
546 error = ng_btsocket_rfcomm_session_create(&s, l2so,
547 &pcb->src, &sa->rfcomm_bdaddr, td);
548 if (error != 0) {
549 mtx_unlock(&ng_btsocket_rfcomm_sessions_mtx);
550 soclose(l2so);
552 return (error);
554 } else if (l2so != NULL)
555 soclose(l2so); /* we don't need new L2CAP socket */
558 * Check if we already have the same DLCI the the same session
561 mtx_lock(&s->session_mtx);
562 mtx_lock(&pcb->pcb_mtx);
564 dlci = RFCOMM_MKDLCI(!INITIATOR(s), sa->rfcomm_channel);
566 if (ng_btsocket_rfcomm_pcb_by_dlci(s, dlci) != NULL) {
567 mtx_unlock(&pcb->pcb_mtx);
568 mtx_unlock(&s->session_mtx);
569 mtx_unlock(&ng_btsocket_rfcomm_sessions_mtx);
571 return (EBUSY);
575 * Check session state and if its not acceptable then refuse connection
578 switch (s->state) {
579 case NG_BTSOCKET_RFCOMM_SESSION_CONNECTING:
580 case NG_BTSOCKET_RFCOMM_SESSION_CONNECTED:
581 case NG_BTSOCKET_RFCOMM_SESSION_OPEN:
583 * Update destination address and channel and attach
584 * DLC to the session
587 bcopy(&sa->rfcomm_bdaddr, &pcb->dst, sizeof(pcb->dst));
588 pcb->channel = sa->rfcomm_channel;
589 pcb->dlci = dlci;
591 LIST_INSERT_HEAD(&s->dlcs, pcb, session_next);
592 pcb->session = s;
594 ng_btsocket_rfcomm_timeout(pcb);
595 soisconnecting(pcb->so);
597 if (s->state == NG_BTSOCKET_RFCOMM_SESSION_OPEN) {
598 pcb->mtu = s->mtu;
599 bcopy(&so2l2cap_pcb(s->l2so)->src, &pcb->src,
600 sizeof(pcb->src));
602 pcb->state = NG_BTSOCKET_RFCOMM_DLC_CONFIGURING;
604 error = ng_btsocket_rfcomm_send_pn(pcb);
605 if (error == 0)
606 error = ng_btsocket_rfcomm_task_wakeup();
607 } else
608 pcb->state = NG_BTSOCKET_RFCOMM_DLC_W4_CONNECT;
609 break;
611 default:
612 error = ECONNRESET;
613 break;
616 mtx_unlock(&pcb->pcb_mtx);
617 mtx_unlock(&s->session_mtx);
618 mtx_unlock(&ng_btsocket_rfcomm_sessions_mtx);
620 return (error);
621 } /* ng_btsocket_rfcomm_connect */
624 * Process ioctl's calls on socket.
625 * XXX FIXME this should provide interface to the RFCOMM multiplexor channel
629 ng_btsocket_rfcomm_control(struct socket *so, u_long cmd, caddr_t data,
630 struct ifnet *ifp, struct thread *td)
632 return (EINVAL);
633 } /* ng_btsocket_rfcomm_control */
636 * Process getsockopt/setsockopt system calls
640 ng_btsocket_rfcomm_ctloutput(struct socket *so, struct sockopt *sopt)
642 ng_btsocket_rfcomm_pcb_p pcb = so2rfcomm_pcb(so);
643 struct ng_btsocket_rfcomm_fc_info fcinfo;
644 int error = 0;
646 if (pcb == NULL)
647 return (EINVAL);
648 if (sopt->sopt_level != SOL_RFCOMM)
649 return (0);
651 mtx_lock(&pcb->pcb_mtx);
653 switch (sopt->sopt_dir) {
654 case SOPT_GET:
655 switch (sopt->sopt_name) {
656 case SO_RFCOMM_MTU:
657 error = sooptcopyout(sopt, &pcb->mtu, sizeof(pcb->mtu));
658 break;
660 case SO_RFCOMM_FC_INFO:
661 fcinfo.lmodem = pcb->lmodem;
662 fcinfo.rmodem = pcb->rmodem;
663 fcinfo.tx_cred = pcb->tx_cred;
664 fcinfo.rx_cred = pcb->rx_cred;
665 fcinfo.cfc = (pcb->flags & NG_BTSOCKET_RFCOMM_DLC_CFC)?
666 1 : 0;
667 fcinfo.reserved = 0;
669 error = sooptcopyout(sopt, &fcinfo, sizeof(fcinfo));
670 break;
672 default:
673 error = ENOPROTOOPT;
674 break;
676 break;
678 case SOPT_SET:
679 switch (sopt->sopt_name) {
680 default:
681 error = ENOPROTOOPT;
682 break;
684 break;
686 default:
687 error = EINVAL;
688 break;
691 mtx_unlock(&pcb->pcb_mtx);
693 return (error);
694 } /* ng_btsocket_rfcomm_ctloutput */
697 * Detach and destroy socket
700 void
701 ng_btsocket_rfcomm_detach(struct socket *so)
703 ng_btsocket_rfcomm_pcb_p pcb = so2rfcomm_pcb(so);
705 KASSERT(pcb != NULL, ("ng_btsocket_rfcomm_detach: pcb == NULL"));
707 mtx_lock(&pcb->pcb_mtx);
709 switch (pcb->state) {
710 case NG_BTSOCKET_RFCOMM_DLC_W4_CONNECT:
711 case NG_BTSOCKET_RFCOMM_DLC_CONFIGURING:
712 case NG_BTSOCKET_RFCOMM_DLC_CONNECTING:
713 case NG_BTSOCKET_RFCOMM_DLC_CONNECTED:
714 /* XXX What to do with pending request? */
715 if (pcb->flags & NG_BTSOCKET_RFCOMM_DLC_TIMO)
716 ng_btsocket_rfcomm_untimeout(pcb);
718 if (pcb->state == NG_BTSOCKET_RFCOMM_DLC_W4_CONNECT)
719 pcb->flags |= NG_BTSOCKET_RFCOMM_DLC_DETACHED;
720 else
721 pcb->state = NG_BTSOCKET_RFCOMM_DLC_DISCONNECTING;
723 ng_btsocket_rfcomm_task_wakeup();
724 break;
726 case NG_BTSOCKET_RFCOMM_DLC_DISCONNECTING:
727 ng_btsocket_rfcomm_task_wakeup();
728 break;
731 while (pcb->state != NG_BTSOCKET_RFCOMM_DLC_CLOSED)
732 msleep(&pcb->state, &pcb->pcb_mtx, PZERO, "rf_det", 0);
734 if (pcb->session != NULL)
735 panic("%s: pcb->session != NULL\n", __func__);
736 if (pcb->flags & NG_BTSOCKET_RFCOMM_DLC_TIMO)
737 panic("%s: timeout on closed DLC, flags=%#x\n",
738 __func__, pcb->flags);
740 mtx_lock(&ng_btsocket_rfcomm_sockets_mtx);
741 LIST_REMOVE(pcb, next);
742 mtx_unlock(&ng_btsocket_rfcomm_sockets_mtx);
744 mtx_unlock(&pcb->pcb_mtx);
746 mtx_destroy(&pcb->pcb_mtx);
747 bzero(pcb, sizeof(*pcb));
748 FREE(pcb, M_NETGRAPH_BTSOCKET_RFCOMM);
750 soisdisconnected(so);
751 so->so_pcb = NULL;
752 } /* ng_btsocket_rfcomm_detach */
755 * Disconnect socket
759 ng_btsocket_rfcomm_disconnect(struct socket *so)
761 ng_btsocket_rfcomm_pcb_p pcb = so2rfcomm_pcb(so);
763 if (pcb == NULL)
764 return (EINVAL);
766 mtx_lock(&pcb->pcb_mtx);
768 if (pcb->state == NG_BTSOCKET_RFCOMM_DLC_DISCONNECTING) {
769 mtx_unlock(&pcb->pcb_mtx);
770 return (EINPROGRESS);
773 /* XXX What to do with pending request? */
774 if (pcb->flags & NG_BTSOCKET_RFCOMM_DLC_TIMO)
775 ng_btsocket_rfcomm_untimeout(pcb);
777 switch (pcb->state) {
778 case NG_BTSOCKET_RFCOMM_DLC_CONFIGURING: /* XXX can we get here? */
779 case NG_BTSOCKET_RFCOMM_DLC_CONNECTING: /* XXX can we get here? */
780 case NG_BTSOCKET_RFCOMM_DLC_CONNECTED:
783 * Just change DLC state and enqueue RFCOMM task. It will
784 * queue and send DISC on the DLC.
787 pcb->state = NG_BTSOCKET_RFCOMM_DLC_DISCONNECTING;
788 soisdisconnecting(so);
790 ng_btsocket_rfcomm_task_wakeup();
791 break;
793 case NG_BTSOCKET_RFCOMM_DLC_CLOSED:
794 case NG_BTSOCKET_RFCOMM_DLC_W4_CONNECT:
795 break;
797 default:
798 panic("%s: Invalid DLC state=%d, flags=%#x\n",
799 __func__, pcb->state, pcb->flags);
800 break;
803 mtx_unlock(&pcb->pcb_mtx);
805 return (0);
806 } /* ng_btsocket_rfcomm_disconnect */
809 * Listen on socket. First call to listen() will create listening RFCOMM session
813 ng_btsocket_rfcomm_listen(struct socket *so, int backlog, struct thread *td)
815 ng_btsocket_rfcomm_pcb_p pcb = so2rfcomm_pcb(so), pcb1;
816 ng_btsocket_rfcomm_session_p s = NULL;
817 struct socket *l2so = NULL;
818 int error, socreate_error, usedchannels;
820 if (pcb == NULL)
821 return (EINVAL);
822 if (pcb->channel > 30)
823 return (EADDRNOTAVAIL);
825 usedchannels = 0;
827 mtx_lock(&pcb->pcb_mtx);
829 if (pcb->channel == 0) {
830 mtx_lock(&ng_btsocket_rfcomm_sockets_mtx);
832 LIST_FOREACH(pcb1, &ng_btsocket_rfcomm_sockets, next)
833 if (pcb1->channel != 0 &&
834 bcmp(&pcb1->src, &pcb->src, sizeof(pcb->src)) == 0)
835 usedchannels |= (1 << (pcb1->channel - 1));
837 for (pcb->channel = 30; pcb->channel > 0; pcb->channel --)
838 if (!(usedchannels & (1 << (pcb->channel - 1))))
839 break;
841 if (pcb->channel == 0) {
842 mtx_unlock(&ng_btsocket_rfcomm_sockets_mtx);
843 mtx_unlock(&pcb->pcb_mtx);
845 return (EADDRNOTAVAIL);
848 mtx_unlock(&ng_btsocket_rfcomm_sockets_mtx);
851 mtx_unlock(&pcb->pcb_mtx);
854 * XXX FIXME - This is FUBAR. socreate() will call soalloc(1), i.e.
855 * soalloc() is allowed to sleep in MALLOC. This creates "could sleep"
856 * WITNESS warnings. To work around this problem we will create L2CAP
857 * socket first and then check if we actually need it. Note that we
858 * will not check for errors in socreate() because if we failed to
859 * create L2CAP socket at this point we still might have already open
860 * session.
863 socreate_error = socreate(PF_BLUETOOTH, &l2so, SOCK_SEQPACKET,
864 BLUETOOTH_PROTO_L2CAP, td->td_ucred, td);
867 * Transition the socket and session into the LISTENING state. Check
868 * for collisions first, as there can only be one.
870 mtx_lock(&ng_btsocket_rfcomm_sessions_mtx);
871 SOCK_LOCK(so);
872 error = solisten_proto_check(so);
873 SOCK_UNLOCK(so);
874 if (error != 0)
875 goto out;
877 LIST_FOREACH(s, &ng_btsocket_rfcomm_sessions, next)
878 if (s->state == NG_BTSOCKET_RFCOMM_SESSION_LISTENING)
879 break;
881 if (s == NULL) {
883 * We need to create default RFCOMM session. Check if we have
884 * L2CAP socket. If l2so == NULL then error has the error code
885 * from socreate()
887 if (l2so == NULL) {
888 error = socreate_error;
889 goto out;
893 * Create default listen RFCOMM session. The default RFCOMM
894 * session will listen on ANY address.
896 * XXX FIXME Note that currently there is no way to adjust MTU
897 * for the default session.
899 error = ng_btsocket_rfcomm_session_create(&s, l2so,
900 NG_HCI_BDADDR_ANY, NULL, td);
901 if (error != 0)
902 goto out;
903 l2so = NULL;
905 SOCK_LOCK(so);
906 solisten_proto(so, backlog);
907 SOCK_UNLOCK(so);
908 out:
909 mtx_unlock(&ng_btsocket_rfcomm_sessions_mtx);
911 * If we still have an l2so reference here, it's unneeded, so release
912 * it.
914 if (l2so != NULL)
915 soclose(l2so);
916 return (error);
917 } /* ng_btsocket_listen */
920 * Get peer address
924 ng_btsocket_rfcomm_peeraddr(struct socket *so, struct sockaddr **nam)
926 ng_btsocket_rfcomm_pcb_p pcb = so2rfcomm_pcb(so);
927 struct sockaddr_rfcomm sa;
929 if (pcb == NULL)
930 return (EINVAL);
932 bcopy(&pcb->dst, &sa.rfcomm_bdaddr, sizeof(sa.rfcomm_bdaddr));
933 sa.rfcomm_channel = pcb->channel;
934 sa.rfcomm_len = sizeof(sa);
935 sa.rfcomm_family = AF_BLUETOOTH;
937 *nam = sodupsockaddr((struct sockaddr *) &sa, M_NOWAIT);
939 return ((*nam == NULL)? ENOMEM : 0);
940 } /* ng_btsocket_rfcomm_peeraddr */
943 * Send data to socket
947 ng_btsocket_rfcomm_send(struct socket *so, int flags, struct mbuf *m,
948 struct sockaddr *nam, struct mbuf *control, struct thread *td)
950 ng_btsocket_rfcomm_pcb_t *pcb = so2rfcomm_pcb(so);
951 int error = 0;
953 /* Check socket and input */
954 if (pcb == NULL || m == NULL || control != NULL) {
955 error = EINVAL;
956 goto drop;
959 mtx_lock(&pcb->pcb_mtx);
961 /* Make sure DLC is connected */
962 if (pcb->state != NG_BTSOCKET_RFCOMM_DLC_CONNECTED) {
963 mtx_unlock(&pcb->pcb_mtx);
964 error = ENOTCONN;
965 goto drop;
968 /* Put the packet on the socket's send queue and wakeup RFCOMM task */
969 sbappend(&pcb->so->so_snd, m);
970 m = NULL;
972 if (!(pcb->flags & NG_BTSOCKET_RFCOMM_DLC_SENDING)) {
973 pcb->flags |= NG_BTSOCKET_RFCOMM_DLC_SENDING;
974 error = ng_btsocket_rfcomm_task_wakeup();
977 mtx_unlock(&pcb->pcb_mtx);
978 drop:
979 NG_FREE_M(m); /* checks for != NULL */
980 NG_FREE_M(control);
982 return (error);
983 } /* ng_btsocket_rfcomm_send */
986 * Get socket address
990 ng_btsocket_rfcomm_sockaddr(struct socket *so, struct sockaddr **nam)
992 ng_btsocket_rfcomm_pcb_p pcb = so2rfcomm_pcb(so);
993 struct sockaddr_rfcomm sa;
995 if (pcb == NULL)
996 return (EINVAL);
998 bcopy(&pcb->src, &sa.rfcomm_bdaddr, sizeof(sa.rfcomm_bdaddr));
999 sa.rfcomm_channel = pcb->channel;
1000 sa.rfcomm_len = sizeof(sa);
1001 sa.rfcomm_family = AF_BLUETOOTH;
1003 *nam = sodupsockaddr((struct sockaddr *) &sa, M_NOWAIT);
1005 return ((*nam == NULL)? ENOMEM : 0);
1006 } /* ng_btsocket_rfcomm_sockaddr */
1009 * Upcall function for L2CAP sockets. Enqueue RFCOMM task.
1012 static void
1013 ng_btsocket_rfcomm_upcall(struct socket *so, void *arg, int waitflag)
1015 int error;
1017 if (so == NULL)
1018 panic("%s: so == NULL\n", __func__);
1020 if ((error = ng_btsocket_rfcomm_task_wakeup()) != 0)
1021 NG_BTSOCKET_RFCOMM_ALERT(
1022 "%s: Could not enqueue RFCOMM task, error=%d\n", __func__, error);
1023 } /* ng_btsocket_rfcomm_upcall */
1026 * RFCOMM task. Will handle all RFCOMM sessions in one pass.
1027 * XXX FIXME does not scale very well
1030 static void
1031 ng_btsocket_rfcomm_sessions_task(void *ctx, int pending)
1033 ng_btsocket_rfcomm_session_p s = NULL, s_next = NULL;
1035 mtx_lock(&ng_btsocket_rfcomm_sessions_mtx);
1037 for (s = LIST_FIRST(&ng_btsocket_rfcomm_sessions); s != NULL; ) {
1038 mtx_lock(&s->session_mtx);
1039 s_next = LIST_NEXT(s, next);
1041 ng_btsocket_rfcomm_session_task(s);
1043 if (s->state == NG_BTSOCKET_RFCOMM_SESSION_CLOSED) {
1044 /* Unlink and clean the session */
1045 LIST_REMOVE(s, next);
1047 NG_BT_MBUFQ_DRAIN(&s->outq);
1048 if (!LIST_EMPTY(&s->dlcs))
1049 panic("%s: DLC list is not empty\n", __func__);
1051 /* Close L2CAP socket */
1052 s->l2so->so_upcallarg = NULL;
1053 s->l2so->so_upcall = NULL;
1054 SOCKBUF_LOCK(&s->l2so->so_rcv);
1055 s->l2so->so_rcv.sb_flags &= ~SB_UPCALL;
1056 SOCKBUF_UNLOCK(&s->l2so->so_rcv);
1057 SOCKBUF_LOCK(&s->l2so->so_snd);
1058 s->l2so->so_snd.sb_flags &= ~SB_UPCALL;
1059 SOCKBUF_UNLOCK(&s->l2so->so_snd);
1060 soclose(s->l2so);
1062 mtx_unlock(&s->session_mtx);
1064 mtx_destroy(&s->session_mtx);
1065 bzero(s, sizeof(*s));
1066 FREE(s, M_NETGRAPH_BTSOCKET_RFCOMM);
1067 } else
1068 mtx_unlock(&s->session_mtx);
1070 s = s_next;
1073 mtx_unlock(&ng_btsocket_rfcomm_sessions_mtx);
1074 } /* ng_btsocket_rfcomm_sessions_task */
1077 * Process RFCOMM session. Will handle all RFCOMM sockets in one pass.
1080 static void
1081 ng_btsocket_rfcomm_session_task(ng_btsocket_rfcomm_session_p s)
1083 mtx_assert(&s->session_mtx, MA_OWNED);
1085 if (s->l2so->so_rcv.sb_state & SBS_CANTRCVMORE) {
1086 NG_BTSOCKET_RFCOMM_INFO(
1087 "%s: L2CAP connection has been terminated, so=%p, so_state=%#x, so_count=%d, " \
1088 "state=%d, flags=%#x\n", __func__, s->l2so, s->l2so->so_state,
1089 s->l2so->so_count, s->state, s->flags);
1091 s->state = NG_BTSOCKET_RFCOMM_SESSION_CLOSED;
1092 ng_btsocket_rfcomm_session_clean(s);
1095 /* Now process upcall */
1096 switch (s->state) {
1097 /* Try to accept new L2CAP connection(s) */
1098 case NG_BTSOCKET_RFCOMM_SESSION_LISTENING:
1099 while (ng_btsocket_rfcomm_session_accept(s) == 0)
1101 break;
1103 /* Process the results of the L2CAP connect */
1104 case NG_BTSOCKET_RFCOMM_SESSION_CONNECTING:
1105 ng_btsocket_rfcomm_session_process_pcb(s);
1107 if (ng_btsocket_rfcomm_session_connect(s) != 0) {
1108 s->state = NG_BTSOCKET_RFCOMM_SESSION_CLOSED;
1109 ng_btsocket_rfcomm_session_clean(s);
1111 break;
1113 /* Try to receive/send more data */
1114 case NG_BTSOCKET_RFCOMM_SESSION_CONNECTED:
1115 case NG_BTSOCKET_RFCOMM_SESSION_OPEN:
1116 case NG_BTSOCKET_RFCOMM_SESSION_DISCONNECTING:
1117 ng_btsocket_rfcomm_session_process_pcb(s);
1119 if (ng_btsocket_rfcomm_session_receive(s) != 0) {
1120 s->state = NG_BTSOCKET_RFCOMM_SESSION_CLOSED;
1121 ng_btsocket_rfcomm_session_clean(s);
1122 } else if (ng_btsocket_rfcomm_session_send(s) != 0) {
1123 s->state = NG_BTSOCKET_RFCOMM_SESSION_CLOSED;
1124 ng_btsocket_rfcomm_session_clean(s);
1126 break;
1128 case NG_BTSOCKET_RFCOMM_SESSION_CLOSED:
1129 break;
1131 default:
1132 panic("%s: Invalid session state=%d, flags=%#x\n",
1133 __func__, s->state, s->flags);
1134 break;
1136 } /* ng_btsocket_rfcomm_session_task */
1139 * Process RFCOMM connection indicator. Caller must hold s->session_mtx
1142 static ng_btsocket_rfcomm_pcb_p
1143 ng_btsocket_rfcomm_connect_ind(ng_btsocket_rfcomm_session_p s, int channel)
1145 ng_btsocket_rfcomm_pcb_p pcb = NULL, pcb1 = NULL;
1146 ng_btsocket_l2cap_pcb_p l2pcb = NULL;
1147 struct socket *so1 = NULL;
1149 mtx_assert(&s->session_mtx, MA_OWNED);
1152 * Try to find RFCOMM socket that listens on given source address
1153 * and channel. This will return the best possible match.
1156 l2pcb = so2l2cap_pcb(s->l2so);
1157 pcb = ng_btsocket_rfcomm_pcb_listener(&l2pcb->src, channel);
1158 if (pcb == NULL)
1159 return (NULL);
1162 * Check the pending connections queue and if we have space then
1163 * create new socket and set proper source and destination address,
1164 * and channel.
1167 mtx_lock(&pcb->pcb_mtx);
1169 if (pcb->so->so_qlen <= pcb->so->so_qlimit)
1170 so1 = sonewconn(pcb->so, 0);
1172 mtx_unlock(&pcb->pcb_mtx);
1174 if (so1 == NULL)
1175 return (NULL);
1178 * If we got here than we have created new socket. So complete the
1179 * connection. Set source and destination address from the session.
1182 pcb1 = so2rfcomm_pcb(so1);
1183 if (pcb1 == NULL)
1184 panic("%s: pcb1 == NULL\n", __func__);
1186 mtx_lock(&pcb1->pcb_mtx);
1188 bcopy(&l2pcb->src, &pcb1->src, sizeof(pcb1->src));
1189 bcopy(&l2pcb->dst, &pcb1->dst, sizeof(pcb1->dst));
1190 pcb1->channel = channel;
1192 /* Link new DLC to the session. We already hold s->session_mtx */
1193 LIST_INSERT_HEAD(&s->dlcs, pcb1, session_next);
1194 pcb1->session = s;
1196 mtx_unlock(&pcb1->pcb_mtx);
1198 return (pcb1);
1199 } /* ng_btsocket_rfcomm_connect_ind */
1202 * Process RFCOMM connect confirmation. Caller must hold s->session_mtx.
1205 static void
1206 ng_btsocket_rfcomm_connect_cfm(ng_btsocket_rfcomm_session_p s)
1208 ng_btsocket_rfcomm_pcb_p pcb = NULL, pcb_next = NULL;
1209 int error;
1211 mtx_assert(&s->session_mtx, MA_OWNED);
1214 * Wake up all waiting sockets and send PN request for each of them.
1215 * Note that timeout already been set in ng_btsocket_rfcomm_connect()
1217 * Note: cannot use LIST_FOREACH because ng_btsocket_rfcomm_pcb_kill
1218 * will unlink DLC from the session
1221 for (pcb = LIST_FIRST(&s->dlcs); pcb != NULL; ) {
1222 mtx_lock(&pcb->pcb_mtx);
1223 pcb_next = LIST_NEXT(pcb, session_next);
1225 if (pcb->state == NG_BTSOCKET_RFCOMM_DLC_W4_CONNECT) {
1226 pcb->mtu = s->mtu;
1227 bcopy(&so2l2cap_pcb(s->l2so)->src, &pcb->src,
1228 sizeof(pcb->src));
1230 error = ng_btsocket_rfcomm_send_pn(pcb);
1231 if (error == 0)
1232 pcb->state = NG_BTSOCKET_RFCOMM_DLC_CONFIGURING;
1233 else
1234 ng_btsocket_rfcomm_pcb_kill(pcb, error);
1237 mtx_unlock(&pcb->pcb_mtx);
1238 pcb = pcb_next;
1240 } /* ng_btsocket_rfcomm_connect_cfm */
1242 /*****************************************************************************
1243 *****************************************************************************
1244 ** RFCOMM sessions
1245 *****************************************************************************
1246 *****************************************************************************/
1249 * Create new RFCOMM session. That function WILL NOT take ownership over l2so.
1250 * Caller MUST free l2so if function failed.
1253 static int
1254 ng_btsocket_rfcomm_session_create(ng_btsocket_rfcomm_session_p *sp,
1255 struct socket *l2so, bdaddr_p src, bdaddr_p dst,
1256 struct thread *td)
1258 ng_btsocket_rfcomm_session_p s = NULL;
1259 struct sockaddr_l2cap l2sa;
1260 struct sockopt l2sopt;
1261 int error;
1262 u_int16_t mtu;
1264 mtx_assert(&ng_btsocket_rfcomm_sessions_mtx, MA_OWNED);
1266 /* Allocate the RFCOMM session */
1267 MALLOC(s, ng_btsocket_rfcomm_session_p, sizeof(*s),
1268 M_NETGRAPH_BTSOCKET_RFCOMM, M_NOWAIT | M_ZERO);
1269 if (s == NULL)
1270 return (ENOMEM);
1272 /* Set defaults */
1273 s->mtu = RFCOMM_DEFAULT_MTU;
1274 s->flags = 0;
1275 s->state = NG_BTSOCKET_RFCOMM_SESSION_CLOSED;
1276 NG_BT_MBUFQ_INIT(&s->outq, ifqmaxlen);
1279 * XXX Mark session mutex as DUPOK to prevent "duplicated lock of
1280 * the same type" message. When accepting new L2CAP connection
1281 * ng_btsocket_rfcomm_session_accept() holds both session mutexes
1282 * for "old" (accepting) session and "new" (created) session.
1285 mtx_init(&s->session_mtx, "btsocks_rfcomm_session_mtx", NULL,
1286 MTX_DEF|MTX_DUPOK);
1288 LIST_INIT(&s->dlcs);
1290 /* Prepare L2CAP socket */
1291 l2so->so_upcallarg = NULL;
1292 l2so->so_upcall = ng_btsocket_rfcomm_upcall;
1293 SOCKBUF_LOCK(&l2so->so_rcv);
1294 l2so->so_rcv.sb_flags |= SB_UPCALL;
1295 SOCKBUF_UNLOCK(&l2so->so_rcv);
1296 SOCKBUF_LOCK(&l2so->so_snd);
1297 l2so->so_snd.sb_flags |= SB_UPCALL;
1298 SOCKBUF_UNLOCK(&l2so->so_snd);
1299 l2so->so_state |= SS_NBIO;
1300 s->l2so = l2so;
1302 mtx_lock(&s->session_mtx);
1305 * "src" == NULL and "dst" == NULL means just create session.
1306 * caller must do the rest
1309 if (src == NULL && dst == NULL)
1310 goto done;
1313 * Set incoming MTU on L2CAP socket. It is RFCOMM session default MTU
1314 * plus 5 bytes: RFCOMM frame header, one extra byte for length and one
1315 * extra byte for credits.
1318 mtu = s->mtu + sizeof(struct rfcomm_frame_hdr) + 1 + 1;
1320 l2sopt.sopt_dir = SOPT_SET;
1321 l2sopt.sopt_level = SOL_L2CAP;
1322 l2sopt.sopt_name = SO_L2CAP_IMTU;
1323 l2sopt.sopt_val = (void *) &mtu;
1324 l2sopt.sopt_valsize = sizeof(mtu);
1325 l2sopt.sopt_td = NULL;
1327 error = sosetopt(s->l2so, &l2sopt);
1328 if (error != 0)
1329 goto bad;
1331 /* Bind socket to "src" address */
1332 l2sa.l2cap_len = sizeof(l2sa);
1333 l2sa.l2cap_family = AF_BLUETOOTH;
1334 l2sa.l2cap_psm = (dst == NULL)? htole16(NG_L2CAP_PSM_RFCOMM) : 0;
1335 bcopy(src, &l2sa.l2cap_bdaddr, sizeof(l2sa.l2cap_bdaddr));
1337 error = sobind(s->l2so, (struct sockaddr *) &l2sa, td);
1338 if (error != 0)
1339 goto bad;
1341 /* If "dst" is not NULL then initiate connect(), otherwise listen() */
1342 if (dst == NULL) {
1343 s->flags = 0;
1344 s->state = NG_BTSOCKET_RFCOMM_SESSION_LISTENING;
1346 error = solisten(s->l2so, 10, td);
1347 if (error != 0)
1348 goto bad;
1349 } else {
1350 s->flags = NG_BTSOCKET_RFCOMM_SESSION_INITIATOR;
1351 s->state = NG_BTSOCKET_RFCOMM_SESSION_CONNECTING;
1353 l2sa.l2cap_len = sizeof(l2sa);
1354 l2sa.l2cap_family = AF_BLUETOOTH;
1355 l2sa.l2cap_psm = htole16(NG_L2CAP_PSM_RFCOMM);
1356 bcopy(dst, &l2sa.l2cap_bdaddr, sizeof(l2sa.l2cap_bdaddr));
1358 error = soconnect(s->l2so, (struct sockaddr *) &l2sa, td);
1359 if (error != 0)
1360 goto bad;
1363 done:
1364 LIST_INSERT_HEAD(&ng_btsocket_rfcomm_sessions, s, next);
1365 *sp = s;
1367 mtx_unlock(&s->session_mtx);
1369 return (0);
1371 bad:
1372 mtx_unlock(&s->session_mtx);
1374 /* Return L2CAP socket back to its original state */
1375 l2so->so_upcallarg = NULL;
1376 l2so->so_upcall = NULL;
1377 SOCKBUF_LOCK(&l2so->so_rcv);
1378 l2so->so_rcv.sb_flags &= ~SB_UPCALL;
1379 SOCKBUF_UNLOCK(&l2so->so_rcv);
1380 SOCKBUF_LOCK(&l2so->so_snd);
1381 l2so->so_snd.sb_flags &= ~SB_UPCALL;
1382 SOCKBUF_UNLOCK(&l2so->so_snd);
1383 l2so->so_state &= ~SS_NBIO;
1385 mtx_destroy(&s->session_mtx);
1386 bzero(s, sizeof(*s));
1387 FREE(s, M_NETGRAPH_BTSOCKET_RFCOMM);
1389 return (error);
1390 } /* ng_btsocket_rfcomm_session_create */
1393 * Process accept() on RFCOMM session
1394 * XXX FIXME locking for "l2so"?
1397 static int
1398 ng_btsocket_rfcomm_session_accept(ng_btsocket_rfcomm_session_p s0)
1400 struct socket *l2so = NULL;
1401 struct sockaddr_l2cap *l2sa = NULL;
1402 ng_btsocket_l2cap_pcb_t *l2pcb = NULL;
1403 ng_btsocket_rfcomm_session_p s = NULL;
1404 int error = 0;
1406 mtx_assert(&ng_btsocket_rfcomm_sessions_mtx, MA_OWNED);
1407 mtx_assert(&s0->session_mtx, MA_OWNED);
1409 /* Check if there is a complete L2CAP connection in the queue */
1410 if ((error = s0->l2so->so_error) != 0) {
1411 NG_BTSOCKET_RFCOMM_ERR(
1412 "%s: Could not accept connection on L2CAP socket, error=%d\n", __func__, error);
1413 s0->l2so->so_error = 0;
1415 return (error);
1418 ACCEPT_LOCK();
1419 if (TAILQ_EMPTY(&s0->l2so->so_comp)) {
1420 ACCEPT_UNLOCK();
1421 if (s0->l2so->so_rcv.sb_state & SBS_CANTRCVMORE)
1422 return (ECONNABORTED);
1423 return (EWOULDBLOCK);
1426 /* Accept incoming L2CAP connection */
1427 l2so = TAILQ_FIRST(&s0->l2so->so_comp);
1428 if (l2so == NULL)
1429 panic("%s: l2so == NULL\n", __func__);
1431 TAILQ_REMOVE(&s0->l2so->so_comp, l2so, so_list);
1432 s0->l2so->so_qlen --;
1433 l2so->so_qstate &= ~SQ_COMP;
1434 l2so->so_head = NULL;
1435 SOCK_LOCK(l2so);
1436 soref(l2so);
1437 l2so->so_state |= SS_NBIO;
1438 SOCK_UNLOCK(l2so);
1439 ACCEPT_UNLOCK();
1441 error = soaccept(l2so, (struct sockaddr **) &l2sa);
1442 if (error != 0) {
1443 NG_BTSOCKET_RFCOMM_ERR(
1444 "%s: soaccept() on L2CAP socket failed, error=%d\n", __func__, error);
1445 soclose(l2so);
1447 return (error);
1451 * Check if there is already active RFCOMM session between two devices.
1452 * If so then close L2CAP connection. We only support one RFCOMM session
1453 * between each pair of devices. Note that here we assume session in any
1454 * state. The session even could be in the middle of disconnecting.
1457 l2pcb = so2l2cap_pcb(l2so);
1458 s = ng_btsocket_rfcomm_session_by_addr(&l2pcb->src, &l2pcb->dst);
1459 if (s == NULL) {
1460 /* Create a new RFCOMM session */
1461 error = ng_btsocket_rfcomm_session_create(&s, l2so, NULL, NULL,
1462 curthread /* XXX */);
1463 if (error == 0) {
1464 mtx_lock(&s->session_mtx);
1466 s->flags = 0;
1467 s->state = NG_BTSOCKET_RFCOMM_SESSION_CONNECTED;
1470 * Adjust MTU on incomming connection. Reserve 5 bytes:
1471 * RFCOMM frame header, one extra byte for length and
1472 * one extra byte for credits.
1475 s->mtu = min(l2pcb->imtu, l2pcb->omtu) -
1476 sizeof(struct rfcomm_frame_hdr) - 1 - 1;
1478 mtx_unlock(&s->session_mtx);
1479 } else {
1480 NG_BTSOCKET_RFCOMM_ALERT(
1481 "%s: Failed to create new RFCOMM session, error=%d\n", __func__, error);
1483 soclose(l2so);
1485 } else {
1486 NG_BTSOCKET_RFCOMM_WARN(
1487 "%s: Rejecting duplicating RFCOMM session between src=%x:%x:%x:%x:%x:%x and " \
1488 "dst=%x:%x:%x:%x:%x:%x, state=%d, flags=%#x\n", __func__,
1489 l2pcb->src.b[5], l2pcb->src.b[4], l2pcb->src.b[3],
1490 l2pcb->src.b[2], l2pcb->src.b[1], l2pcb->src.b[0],
1491 l2pcb->dst.b[5], l2pcb->dst.b[4], l2pcb->dst.b[3],
1492 l2pcb->dst.b[2], l2pcb->dst.b[1], l2pcb->dst.b[0],
1493 s->state, s->flags);
1495 error = EBUSY;
1496 soclose(l2so);
1499 return (error);
1500 } /* ng_btsocket_rfcomm_session_accept */
1503 * Process connect() on RFCOMM session
1504 * XXX FIXME locking for "l2so"?
1507 static int
1508 ng_btsocket_rfcomm_session_connect(ng_btsocket_rfcomm_session_p s)
1510 ng_btsocket_l2cap_pcb_p l2pcb = so2l2cap_pcb(s->l2so);
1511 int error;
1513 mtx_assert(&s->session_mtx, MA_OWNED);
1515 /* First check if connection has failed */
1516 if ((error = s->l2so->so_error) != 0) {
1517 s->l2so->so_error = 0;
1519 NG_BTSOCKET_RFCOMM_ERR(
1520 "%s: Could not connect RFCOMM session, error=%d, state=%d, flags=%#x\n",
1521 __func__, error, s->state, s->flags);
1523 return (error);
1526 /* Is connection still in progress? */
1527 if (s->l2so->so_state & SS_ISCONNECTING)
1528 return (0);
1531 * If we got here then we are connected. Send SABM on DLCI 0 to
1532 * open multiplexor channel.
1535 if (error == 0) {
1536 s->state = NG_BTSOCKET_RFCOMM_SESSION_CONNECTED;
1539 * Adjust MTU on outgoing connection. Reserve 5 bytes: RFCOMM
1540 * frame header, one extra byte for length and one extra byte
1541 * for credits.
1544 s->mtu = min(l2pcb->imtu, l2pcb->omtu) -
1545 sizeof(struct rfcomm_frame_hdr) - 1 - 1;
1547 error = ng_btsocket_rfcomm_send_command(s,RFCOMM_FRAME_SABM,0);
1548 if (error == 0)
1549 error = ng_btsocket_rfcomm_task_wakeup();
1552 return (error);
1553 }/* ng_btsocket_rfcomm_session_connect */
1556 * Receive data on RFCOMM session
1557 * XXX FIXME locking for "l2so"?
1560 static int
1561 ng_btsocket_rfcomm_session_receive(ng_btsocket_rfcomm_session_p s)
1563 struct mbuf *m = NULL;
1564 struct uio uio;
1565 int more, flags, error;
1567 mtx_assert(&s->session_mtx, MA_OWNED);
1569 /* Can we read from the L2CAP socket? */
1570 if (!soreadable(s->l2so))
1571 return (0);
1573 /* First check for error on L2CAP socket */
1574 if ((error = s->l2so->so_error) != 0) {
1575 s->l2so->so_error = 0;
1577 NG_BTSOCKET_RFCOMM_ERR(
1578 "%s: Could not receive data from L2CAP socket, error=%d, state=%d, flags=%#x\n",
1579 __func__, error, s->state, s->flags);
1581 return (error);
1585 * Read all packets from the L2CAP socket.
1586 * XXX FIXME/VERIFY is that correct? For now use m->m_nextpkt as
1587 * indication that there is more packets on the socket's buffer.
1588 * Also what should we use in uio.uio_resid?
1589 * May be s->mtu + sizeof(struct rfcomm_frame_hdr) + 1 + 1?
1592 for (more = 1; more; ) {
1593 /* Try to get next packet from socket */
1594 bzero(&uio, sizeof(uio));
1595 /* uio.uio_td = NULL; */
1596 uio.uio_resid = 1000000000;
1597 flags = MSG_DONTWAIT;
1599 m = NULL;
1600 error = soreceive(s->l2so, NULL, &uio, &m,
1601 (struct mbuf **) NULL, &flags);
1602 if (error != 0) {
1603 if (error == EWOULDBLOCK)
1604 return (0); /* XXX can happen? */
1606 NG_BTSOCKET_RFCOMM_ERR(
1607 "%s: Could not receive data from L2CAP socket, error=%d\n", __func__, error);
1609 return (error);
1612 more = (m->m_nextpkt != NULL);
1613 m->m_nextpkt = NULL;
1615 ng_btsocket_rfcomm_receive_frame(s, m);
1618 return (0);
1619 } /* ng_btsocket_rfcomm_session_receive */
1622 * Send data on RFCOMM session
1623 * XXX FIXME locking for "l2so"?
1626 static int
1627 ng_btsocket_rfcomm_session_send(ng_btsocket_rfcomm_session_p s)
1629 struct mbuf *m = NULL;
1630 int error;
1632 mtx_assert(&s->session_mtx, MA_OWNED);
1634 /* Send as much as we can from the session queue */
1635 while (sowriteable(s->l2so)) {
1636 /* Check if socket still OK */
1637 if ((error = s->l2so->so_error) != 0) {
1638 s->l2so->so_error = 0;
1640 NG_BTSOCKET_RFCOMM_ERR(
1641 "%s: Detected error=%d on L2CAP socket, state=%d, flags=%#x\n",
1642 __func__, error, s->state, s->flags);
1644 return (error);
1647 NG_BT_MBUFQ_DEQUEUE(&s->outq, m);
1648 if (m == NULL)
1649 return (0); /* we are done */
1651 /* Call send function on the L2CAP socket */
1652 error = (*s->l2so->so_proto->pr_usrreqs->pru_send)(s->l2so,
1653 0, m, NULL, NULL, curthread /* XXX */);
1654 if (error != 0) {
1655 NG_BTSOCKET_RFCOMM_ERR(
1656 "%s: Could not send data to L2CAP socket, error=%d\n", __func__, error);
1658 return (error);
1662 return (0);
1663 } /* ng_btsocket_rfcomm_session_send */
1666 * Close and disconnect all DLCs for the given session. Caller must hold
1667 * s->sesson_mtx. Will wakeup session.
1670 static void
1671 ng_btsocket_rfcomm_session_clean(ng_btsocket_rfcomm_session_p s)
1673 ng_btsocket_rfcomm_pcb_p pcb = NULL, pcb_next = NULL;
1674 int error;
1676 mtx_assert(&s->session_mtx, MA_OWNED);
1679 * Note: cannot use LIST_FOREACH because ng_btsocket_rfcomm_pcb_kill
1680 * will unlink DLC from the session
1683 for (pcb = LIST_FIRST(&s->dlcs); pcb != NULL; ) {
1684 mtx_lock(&pcb->pcb_mtx);
1685 pcb_next = LIST_NEXT(pcb, session_next);
1687 NG_BTSOCKET_RFCOMM_INFO(
1688 "%s: Disconnecting dlci=%d, state=%d, flags=%#x\n",
1689 __func__, pcb->dlci, pcb->state, pcb->flags);
1691 if (pcb->state == NG_BTSOCKET_RFCOMM_DLC_CONNECTED)
1692 error = ECONNRESET;
1693 else
1694 error = ECONNREFUSED;
1696 ng_btsocket_rfcomm_pcb_kill(pcb, error);
1698 mtx_unlock(&pcb->pcb_mtx);
1699 pcb = pcb_next;
1701 } /* ng_btsocket_rfcomm_session_clean */
1704 * Process all DLCs on the session. Caller MUST hold s->session_mtx.
1707 static void
1708 ng_btsocket_rfcomm_session_process_pcb(ng_btsocket_rfcomm_session_p s)
1710 ng_btsocket_rfcomm_pcb_p pcb = NULL, pcb_next = NULL;
1711 int error;
1713 mtx_assert(&s->session_mtx, MA_OWNED);
1716 * Note: cannot use LIST_FOREACH because ng_btsocket_rfcomm_pcb_kill
1717 * will unlink DLC from the session
1720 for (pcb = LIST_FIRST(&s->dlcs); pcb != NULL; ) {
1721 mtx_lock(&pcb->pcb_mtx);
1722 pcb_next = LIST_NEXT(pcb, session_next);
1724 switch (pcb->state) {
1727 * If DLC in W4_CONNECT state then we should check for both
1728 * timeout and detach.
1731 case NG_BTSOCKET_RFCOMM_DLC_W4_CONNECT:
1732 if (pcb->flags & NG_BTSOCKET_RFCOMM_DLC_DETACHED)
1733 ng_btsocket_rfcomm_pcb_kill(pcb, 0);
1734 else if (pcb->flags & NG_BTSOCKET_RFCOMM_DLC_TIMEDOUT)
1735 ng_btsocket_rfcomm_pcb_kill(pcb, ETIMEDOUT);
1736 break;
1739 * If DLC in CONFIGURING or CONNECTING state then we only
1740 * should check for timeout. If detach() was called then
1741 * DLC will be moved into DISCONNECTING state.
1744 case NG_BTSOCKET_RFCOMM_DLC_CONFIGURING:
1745 case NG_BTSOCKET_RFCOMM_DLC_CONNECTING:
1746 if (pcb->flags & NG_BTSOCKET_RFCOMM_DLC_TIMEDOUT)
1747 ng_btsocket_rfcomm_pcb_kill(pcb, ETIMEDOUT);
1748 break;
1751 * If DLC in CONNECTED state then we need to send data (if any)
1752 * from the socket's send queue. Note that we will send data
1753 * from either all sockets or none. This may overload session's
1754 * outgoing queue (but we do not check for that).
1756 * XXX FIXME need scheduler for RFCOMM sockets
1759 case NG_BTSOCKET_RFCOMM_DLC_CONNECTED:
1760 error = ng_btsocket_rfcomm_pcb_send(pcb, ALOT);
1761 if (error != 0)
1762 ng_btsocket_rfcomm_pcb_kill(pcb, error);
1763 break;
1766 * If DLC in DISCONNECTING state then we must send DISC frame.
1767 * Note that if DLC has timeout set then we do not need to
1768 * resend DISC frame.
1770 * XXX FIXME need to drain all data from the socket's queue
1771 * if LINGER option was set
1774 case NG_BTSOCKET_RFCOMM_DLC_DISCONNECTING:
1775 if (!(pcb->flags & NG_BTSOCKET_RFCOMM_DLC_TIMO)) {
1776 error = ng_btsocket_rfcomm_send_command(
1777 pcb->session, RFCOMM_FRAME_DISC,
1778 pcb->dlci);
1779 if (error == 0)
1780 ng_btsocket_rfcomm_timeout(pcb);
1781 else
1782 ng_btsocket_rfcomm_pcb_kill(pcb, error);
1783 } else if (pcb->flags & NG_BTSOCKET_RFCOMM_DLC_TIMEDOUT)
1784 ng_btsocket_rfcomm_pcb_kill(pcb, ETIMEDOUT);
1785 break;
1787 /* case NG_BTSOCKET_RFCOMM_DLC_CLOSED: */
1788 default:
1789 panic("%s: Invalid DLC state=%d, flags=%#x\n",
1790 __func__, pcb->state, pcb->flags);
1791 break;
1794 mtx_unlock(&pcb->pcb_mtx);
1795 pcb = pcb_next;
1797 } /* ng_btsocket_rfcomm_session_process_pcb */
1800 * Find RFCOMM session between "src" and "dst".
1801 * Caller MUST hold ng_btsocket_rfcomm_sessions_mtx.
1804 static ng_btsocket_rfcomm_session_p
1805 ng_btsocket_rfcomm_session_by_addr(bdaddr_p src, bdaddr_p dst)
1807 ng_btsocket_rfcomm_session_p s = NULL;
1808 ng_btsocket_l2cap_pcb_p l2pcb = NULL;
1809 int any_src;
1811 mtx_assert(&ng_btsocket_rfcomm_sessions_mtx, MA_OWNED);
1813 any_src = (bcmp(src, NG_HCI_BDADDR_ANY, sizeof(*src)) == 0);
1815 LIST_FOREACH(s, &ng_btsocket_rfcomm_sessions, next) {
1816 l2pcb = so2l2cap_pcb(s->l2so);
1818 if ((any_src || bcmp(&l2pcb->src, src, sizeof(*src)) == 0) &&
1819 bcmp(&l2pcb->dst, dst, sizeof(*dst)) == 0)
1820 break;
1823 return (s);
1824 } /* ng_btsocket_rfcomm_session_by_addr */
1826 /*****************************************************************************
1827 *****************************************************************************
1828 ** RFCOMM
1829 *****************************************************************************
1830 *****************************************************************************/
1833 * Process incoming RFCOMM frame. Caller must hold s->session_mtx.
1834 * XXX FIXME check frame length
1837 static int
1838 ng_btsocket_rfcomm_receive_frame(ng_btsocket_rfcomm_session_p s,
1839 struct mbuf *m0)
1841 struct rfcomm_frame_hdr *hdr = NULL;
1842 struct mbuf *m = NULL;
1843 u_int16_t length;
1844 u_int8_t dlci, type;
1845 int error = 0;
1847 mtx_assert(&s->session_mtx, MA_OWNED);
1849 /* Pullup as much as we can into first mbuf (for direct access) */
1850 length = min(m0->m_pkthdr.len, MHLEN);
1851 if (m0->m_len < length) {
1852 if ((m0 = m_pullup(m0, length)) == NULL) {
1853 NG_BTSOCKET_RFCOMM_ALERT(
1854 "%s: m_pullup(%d) failed\n", __func__, length);
1856 return (ENOBUFS);
1860 hdr = mtod(m0, struct rfcomm_frame_hdr *);
1861 dlci = RFCOMM_DLCI(hdr->address);
1862 type = RFCOMM_TYPE(hdr->control);
1864 /* Test EA bit in length. If not set then we have 2 bytes of length */
1865 if (!RFCOMM_EA(hdr->length)) {
1866 bcopy(&hdr->length, &length, sizeof(length));
1867 length = le16toh(length) >> 1;
1868 m_adj(m0, sizeof(*hdr) + 1);
1869 } else {
1870 length = hdr->length >> 1;
1871 m_adj(m0, sizeof(*hdr));
1874 NG_BTSOCKET_RFCOMM_INFO(
1875 "%s: Got frame type=%#x, dlci=%d, length=%d, cr=%d, pf=%d, len=%d\n",
1876 __func__, type, dlci, length, RFCOMM_CR(hdr->address),
1877 RFCOMM_PF(hdr->control), m0->m_pkthdr.len);
1880 * Get FCS (the last byte in the frame)
1881 * XXX this will not work if mbuf chain ends with empty mbuf.
1882 * XXX let's hope it never happens :)
1885 for (m = m0; m->m_next != NULL; m = m->m_next)
1887 if (m->m_len <= 0)
1888 panic("%s: Empty mbuf at the end of the chain, len=%d\n",
1889 __func__, m->m_len);
1892 * Check FCS. We only need to calculate FCS on first 2 or 3 bytes
1893 * and already m_pullup'ed mbuf chain, so it should be safe.
1896 if (ng_btsocket_rfcomm_check_fcs((u_int8_t *) hdr, type, m->m_data[m->m_len - 1])) {
1897 NG_BTSOCKET_RFCOMM_ERR(
1898 "%s: Invalid RFCOMM packet. Bad checksum\n", __func__);
1899 NG_FREE_M(m0);
1901 return (EINVAL);
1904 m_adj(m0, -1); /* Trim FCS byte */
1907 * Process RFCOMM frame.
1909 * From TS 07.10 spec
1911 * "... In the case where a SABM or DISC command with the P bit set
1912 * to 0 is received then the received frame shall be discarded..."
1914 * "... If a unsolicited DM response is received then the frame shall
1915 * be processed irrespective of the P/F setting... "
1917 * "... The station may transmit response frames with the F bit set
1918 * to 0 at any opportunity on an asynchronous basis. However, in the
1919 * case where a UA response is received with the F bit set to 0 then
1920 * the received frame shall be discarded..."
1922 * From Bluetooth spec
1924 * "... When credit based flow control is being used, the meaning of
1925 * the P/F bit in the control field of the RFCOMM header is redefined
1926 * for UIH frames..."
1929 switch (type) {
1930 case RFCOMM_FRAME_SABM:
1931 if (RFCOMM_PF(hdr->control))
1932 error = ng_btsocket_rfcomm_receive_sabm(s, dlci);
1933 break;
1935 case RFCOMM_FRAME_DISC:
1936 if (RFCOMM_PF(hdr->control))
1937 error = ng_btsocket_rfcomm_receive_disc(s, dlci);
1938 break;
1940 case RFCOMM_FRAME_UA:
1941 if (RFCOMM_PF(hdr->control))
1942 error = ng_btsocket_rfcomm_receive_ua(s, dlci);
1943 break;
1945 case RFCOMM_FRAME_DM:
1946 error = ng_btsocket_rfcomm_receive_dm(s, dlci);
1947 break;
1949 case RFCOMM_FRAME_UIH:
1950 if (dlci == 0)
1951 error = ng_btsocket_rfcomm_receive_mcc(s, m0);
1952 else
1953 error = ng_btsocket_rfcomm_receive_uih(s, dlci,
1954 RFCOMM_PF(hdr->control), m0);
1956 return (error);
1957 /* NOT REACHED */
1959 default:
1960 NG_BTSOCKET_RFCOMM_ERR(
1961 "%s: Invalid RFCOMM packet. Unknown type=%#x\n", __func__, type);
1962 error = EINVAL;
1963 break;
1966 NG_FREE_M(m0);
1968 return (error);
1969 } /* ng_btsocket_rfcomm_receive_frame */
1972 * Process RFCOMM SABM frame
1975 static int
1976 ng_btsocket_rfcomm_receive_sabm(ng_btsocket_rfcomm_session_p s, int dlci)
1978 ng_btsocket_rfcomm_pcb_p pcb = NULL;
1979 int error = 0;
1981 mtx_assert(&s->session_mtx, MA_OWNED);
1983 NG_BTSOCKET_RFCOMM_INFO(
1984 "%s: Got SABM, session state=%d, flags=%#x, mtu=%d, dlci=%d\n",
1985 __func__, s->state, s->flags, s->mtu, dlci);
1987 /* DLCI == 0 means open multiplexor channel */
1988 if (dlci == 0) {
1989 switch (s->state) {
1990 case NG_BTSOCKET_RFCOMM_SESSION_CONNECTED:
1991 case NG_BTSOCKET_RFCOMM_SESSION_OPEN:
1992 error = ng_btsocket_rfcomm_send_command(s,
1993 RFCOMM_FRAME_UA, dlci);
1994 if (error == 0) {
1995 s->state = NG_BTSOCKET_RFCOMM_SESSION_OPEN;
1996 ng_btsocket_rfcomm_connect_cfm(s);
1997 } else {
1998 s->state = NG_BTSOCKET_RFCOMM_SESSION_CLOSED;
1999 ng_btsocket_rfcomm_session_clean(s);
2001 break;
2003 default:
2004 NG_BTSOCKET_RFCOMM_WARN(
2005 "%s: Got SABM for session in invalid state state=%d, flags=%#x\n",
2006 __func__, s->state, s->flags);
2007 error = EINVAL;
2008 break;
2011 return (error);
2014 /* Make sure multiplexor channel is open */
2015 if (s->state != NG_BTSOCKET_RFCOMM_SESSION_OPEN) {
2016 NG_BTSOCKET_RFCOMM_ERR(
2017 "%s: Got SABM for dlci=%d with mulitplexor channel closed, state=%d, " \
2018 "flags=%#x\n", __func__, dlci, s->state, s->flags);
2020 return (EINVAL);
2024 * Check if we have this DLCI. This might happen when remote
2025 * peer uses PN command before actual open (SABM) happens.
2028 pcb = ng_btsocket_rfcomm_pcb_by_dlci(s, dlci);
2029 if (pcb != NULL) {
2030 mtx_lock(&pcb->pcb_mtx);
2032 if (pcb->state != NG_BTSOCKET_RFCOMM_DLC_CONNECTING) {
2033 NG_BTSOCKET_RFCOMM_ERR(
2034 "%s: Got SABM for dlci=%d in invalid state=%d, flags=%#x\n",
2035 __func__, dlci, pcb->state, pcb->flags);
2036 mtx_unlock(&pcb->pcb_mtx);
2038 return (ENOENT);
2041 ng_btsocket_rfcomm_untimeout(pcb);
2043 error = ng_btsocket_rfcomm_send_command(s,RFCOMM_FRAME_UA,dlci);
2044 if (error == 0)
2045 error = ng_btsocket_rfcomm_send_msc(pcb);
2047 if (error == 0) {
2048 pcb->state = NG_BTSOCKET_RFCOMM_DLC_CONNECTED;
2049 soisconnected(pcb->so);
2050 } else
2051 ng_btsocket_rfcomm_pcb_kill(pcb, error);
2053 mtx_unlock(&pcb->pcb_mtx);
2055 return (error);
2059 * We do not have requested DLCI, so it must be an incoming connection
2060 * with default parameters. Try to accept it.
2063 pcb = ng_btsocket_rfcomm_connect_ind(s, RFCOMM_SRVCHANNEL(dlci));
2064 if (pcb != NULL) {
2065 mtx_lock(&pcb->pcb_mtx);
2067 pcb->dlci = dlci;
2069 error = ng_btsocket_rfcomm_send_command(s,RFCOMM_FRAME_UA,dlci);
2070 if (error == 0)
2071 error = ng_btsocket_rfcomm_send_msc(pcb);
2073 if (error == 0) {
2074 pcb->state = NG_BTSOCKET_RFCOMM_DLC_CONNECTED;
2075 soisconnected(pcb->so);
2076 } else
2077 ng_btsocket_rfcomm_pcb_kill(pcb, error);
2079 mtx_unlock(&pcb->pcb_mtx);
2080 } else
2081 /* Nobody is listen()ing on the requested DLCI */
2082 error = ng_btsocket_rfcomm_send_command(s,RFCOMM_FRAME_DM,dlci);
2084 return (error);
2085 } /* ng_btsocket_rfcomm_receive_sabm */
2088 * Process RFCOMM DISC frame
2091 static int
2092 ng_btsocket_rfcomm_receive_disc(ng_btsocket_rfcomm_session_p s, int dlci)
2094 ng_btsocket_rfcomm_pcb_p pcb = NULL;
2095 int error = 0;
2097 mtx_assert(&s->session_mtx, MA_OWNED);
2099 NG_BTSOCKET_RFCOMM_INFO(
2100 "%s: Got DISC, session state=%d, flags=%#x, mtu=%d, dlci=%d\n",
2101 __func__, s->state, s->flags, s->mtu, dlci);
2103 /* DLCI == 0 means close multiplexor channel */
2104 if (dlci == 0) {
2105 /* XXX FIXME assume that remote side will close the socket */
2106 error = ng_btsocket_rfcomm_send_command(s, RFCOMM_FRAME_UA, 0);
2107 if (error == 0) {
2108 if (s->state == NG_BTSOCKET_RFCOMM_SESSION_DISCONNECTING)
2109 s->state = NG_BTSOCKET_RFCOMM_SESSION_CLOSED; /* XXX */
2110 else
2111 s->state = NG_BTSOCKET_RFCOMM_SESSION_DISCONNECTING;
2112 } else
2113 s->state = NG_BTSOCKET_RFCOMM_SESSION_CLOSED; /* XXX */
2115 ng_btsocket_rfcomm_session_clean(s);
2116 } else {
2117 pcb = ng_btsocket_rfcomm_pcb_by_dlci(s, dlci);
2118 if (pcb != NULL) {
2119 int err;
2121 mtx_lock(&pcb->pcb_mtx);
2123 NG_BTSOCKET_RFCOMM_INFO(
2124 "%s: Got DISC for dlci=%d, state=%d, flags=%#x\n",
2125 __func__, dlci, pcb->state, pcb->flags);
2127 error = ng_btsocket_rfcomm_send_command(s,
2128 RFCOMM_FRAME_UA, dlci);
2130 if (pcb->state == NG_BTSOCKET_RFCOMM_DLC_CONNECTED)
2131 err = 0;
2132 else
2133 err = ECONNREFUSED;
2135 ng_btsocket_rfcomm_pcb_kill(pcb, err);
2137 mtx_unlock(&pcb->pcb_mtx);
2138 } else {
2139 NG_BTSOCKET_RFCOMM_WARN(
2140 "%s: Got DISC for non-existing dlci=%d\n", __func__, dlci);
2142 error = ng_btsocket_rfcomm_send_command(s,
2143 RFCOMM_FRAME_DM, dlci);
2147 return (error);
2148 } /* ng_btsocket_rfcomm_receive_disc */
2151 * Process RFCOMM UA frame
2154 static int
2155 ng_btsocket_rfcomm_receive_ua(ng_btsocket_rfcomm_session_p s, int dlci)
2157 ng_btsocket_rfcomm_pcb_p pcb = NULL;
2158 int error = 0;
2160 mtx_assert(&s->session_mtx, MA_OWNED);
2162 NG_BTSOCKET_RFCOMM_INFO(
2163 "%s: Got UA, session state=%d, flags=%#x, mtu=%d, dlci=%d\n",
2164 __func__, s->state, s->flags, s->mtu, dlci);
2166 /* dlci == 0 means multiplexor channel */
2167 if (dlci == 0) {
2168 switch (s->state) {
2169 case NG_BTSOCKET_RFCOMM_SESSION_CONNECTED:
2170 s->state = NG_BTSOCKET_RFCOMM_SESSION_OPEN;
2171 ng_btsocket_rfcomm_connect_cfm(s);
2172 break;
2174 case NG_BTSOCKET_RFCOMM_SESSION_DISCONNECTING:
2175 s->state = NG_BTSOCKET_RFCOMM_SESSION_CLOSED;
2176 ng_btsocket_rfcomm_session_clean(s);
2177 break;
2179 default:
2180 NG_BTSOCKET_RFCOMM_WARN(
2181 "%s: Got UA for session in invalid state=%d(%d), flags=%#x, mtu=%d\n",
2182 __func__, s->state, INITIATOR(s), s->flags,
2183 s->mtu);
2184 error = ENOENT;
2185 break;
2188 return (error);
2191 /* Check if we have this DLCI */
2192 pcb = ng_btsocket_rfcomm_pcb_by_dlci(s, dlci);
2193 if (pcb != NULL) {
2194 mtx_lock(&pcb->pcb_mtx);
2196 NG_BTSOCKET_RFCOMM_INFO(
2197 "%s: Got UA for dlci=%d, state=%d, flags=%#x\n",
2198 __func__, dlci, pcb->state, pcb->flags);
2200 switch (pcb->state) {
2201 case NG_BTSOCKET_RFCOMM_DLC_CONNECTING:
2202 ng_btsocket_rfcomm_untimeout(pcb);
2204 error = ng_btsocket_rfcomm_send_msc(pcb);
2205 if (error == 0) {
2206 pcb->state = NG_BTSOCKET_RFCOMM_DLC_CONNECTED;
2207 soisconnected(pcb->so);
2209 break;
2211 case NG_BTSOCKET_RFCOMM_DLC_DISCONNECTING:
2212 ng_btsocket_rfcomm_pcb_kill(pcb, 0);
2213 break;
2215 default:
2216 NG_BTSOCKET_RFCOMM_WARN(
2217 "%s: Got UA for dlci=%d in invalid state=%d, flags=%#x\n",
2218 __func__, dlci, pcb->state, pcb->flags);
2219 error = ENOENT;
2220 break;
2223 mtx_unlock(&pcb->pcb_mtx);
2224 } else {
2225 NG_BTSOCKET_RFCOMM_WARN(
2226 "%s: Got UA for non-existing dlci=%d\n", __func__, dlci);
2228 error = ng_btsocket_rfcomm_send_command(s,RFCOMM_FRAME_DM,dlci);
2231 return (error);
2232 } /* ng_btsocket_rfcomm_receive_ua */
2235 * Process RFCOMM DM frame
2238 static int
2239 ng_btsocket_rfcomm_receive_dm(ng_btsocket_rfcomm_session_p s, int dlci)
2241 ng_btsocket_rfcomm_pcb_p pcb = NULL;
2242 int error;
2244 mtx_assert(&s->session_mtx, MA_OWNED);
2246 NG_BTSOCKET_RFCOMM_INFO(
2247 "%s: Got DM, session state=%d, flags=%#x, mtu=%d, dlci=%d\n",
2248 __func__, s->state, s->flags, s->mtu, dlci);
2250 /* DLCI == 0 means multiplexor channel */
2251 if (dlci == 0) {
2252 /* Disconnect all dlc's on the session */
2253 s->state = NG_BTSOCKET_RFCOMM_SESSION_CLOSED;
2254 ng_btsocket_rfcomm_session_clean(s);
2255 } else {
2256 pcb = ng_btsocket_rfcomm_pcb_by_dlci(s, dlci);
2257 if (pcb != NULL) {
2258 mtx_lock(&pcb->pcb_mtx);
2260 NG_BTSOCKET_RFCOMM_INFO(
2261 "%s: Got DM for dlci=%d, state=%d, flags=%#x\n",
2262 __func__, dlci, pcb->state, pcb->flags);
2264 if (pcb->state == NG_BTSOCKET_RFCOMM_DLC_CONNECTED)
2265 error = ECONNRESET;
2266 else
2267 error = ECONNREFUSED;
2269 ng_btsocket_rfcomm_pcb_kill(pcb, error);
2271 mtx_unlock(&pcb->pcb_mtx);
2272 } else
2273 NG_BTSOCKET_RFCOMM_WARN(
2274 "%s: Got DM for non-existing dlci=%d\n", __func__, dlci);
2277 return (0);
2278 } /* ng_btsocket_rfcomm_receive_dm */
2281 * Process RFCOMM UIH frame (data)
2284 static int
2285 ng_btsocket_rfcomm_receive_uih(ng_btsocket_rfcomm_session_p s, int dlci,
2286 int pf, struct mbuf *m0)
2288 ng_btsocket_rfcomm_pcb_p pcb = NULL;
2289 int error = 0;
2291 mtx_assert(&s->session_mtx, MA_OWNED);
2293 NG_BTSOCKET_RFCOMM_INFO(
2294 "%s: Got UIH, session state=%d, flags=%#x, mtu=%d, dlci=%d, pf=%d, len=%d\n",
2295 __func__, s->state, s->flags, s->mtu, dlci, pf,
2296 m0->m_pkthdr.len);
2298 /* XXX should we do it here? Check for session flow control */
2299 if (s->flags & NG_BTSOCKET_RFCOMM_SESSION_LFC) {
2300 NG_BTSOCKET_RFCOMM_WARN(
2301 "%s: Got UIH with session flow control asserted, state=%d, flags=%#x\n",
2302 __func__, s->state, s->flags);
2303 goto drop;
2306 /* Check if we have this dlci */
2307 pcb = ng_btsocket_rfcomm_pcb_by_dlci(s, dlci);
2308 if (pcb == NULL) {
2309 NG_BTSOCKET_RFCOMM_WARN(
2310 "%s: Got UIH for non-existing dlci=%d\n", __func__, dlci);
2311 error = ng_btsocket_rfcomm_send_command(s,RFCOMM_FRAME_DM,dlci);
2312 goto drop;
2315 mtx_lock(&pcb->pcb_mtx);
2317 /* Check dlci state */
2318 if (pcb->state != NG_BTSOCKET_RFCOMM_DLC_CONNECTED) {
2319 NG_BTSOCKET_RFCOMM_WARN(
2320 "%s: Got UIH for dlci=%d in invalid state=%d, flags=%#x\n",
2321 __func__, dlci, pcb->state, pcb->flags);
2322 error = EINVAL;
2323 goto drop1;
2326 /* Check dlci flow control */
2327 if (((pcb->flags & NG_BTSOCKET_RFCOMM_DLC_CFC) && pcb->rx_cred <= 0) ||
2328 (pcb->lmodem & RFCOMM_MODEM_FC)) {
2329 NG_BTSOCKET_RFCOMM_ERR(
2330 "%s: Got UIH for dlci=%d with asserted flow control, state=%d, " \
2331 "flags=%#x, rx_cred=%d, lmodem=%#x\n",
2332 __func__, dlci, pcb->state, pcb->flags,
2333 pcb->rx_cred, pcb->lmodem);
2334 goto drop1;
2337 /* Did we get any credits? */
2338 if ((pcb->flags & NG_BTSOCKET_RFCOMM_DLC_CFC) && pf) {
2339 NG_BTSOCKET_RFCOMM_INFO(
2340 "%s: Got %d more credits for dlci=%d, state=%d, flags=%#x, " \
2341 "rx_cred=%d, tx_cred=%d\n",
2342 __func__, *mtod(m0, u_int8_t *), dlci, pcb->state,
2343 pcb->flags, pcb->rx_cred, pcb->tx_cred);
2345 pcb->tx_cred += *mtod(m0, u_int8_t *);
2346 m_adj(m0, 1);
2348 /* Send more from the DLC. XXX check for errors? */
2349 ng_btsocket_rfcomm_pcb_send(pcb, ALOT);
2352 /* OK the of the rest of the mbuf is the data */
2353 if (m0->m_pkthdr.len > 0) {
2354 /* If we are using credit flow control decrease rx_cred here */
2355 if (pcb->flags & NG_BTSOCKET_RFCOMM_DLC_CFC) {
2356 /* Give remote peer more credits (if needed) */
2357 if (-- pcb->rx_cred <= RFCOMM_MAX_CREDITS / 2)
2358 ng_btsocket_rfcomm_send_credits(pcb);
2359 else
2360 NG_BTSOCKET_RFCOMM_INFO(
2361 "%s: Remote side still has credits, dlci=%d, state=%d, flags=%#x, " \
2362 "rx_cred=%d, tx_cred=%d\n", __func__, dlci, pcb->state, pcb->flags,
2363 pcb->rx_cred, pcb->tx_cred);
2366 /* Check packet against mtu on dlci */
2367 if (m0->m_pkthdr.len > pcb->mtu) {
2368 NG_BTSOCKET_RFCOMM_ERR(
2369 "%s: Got oversized UIH for dlci=%d, state=%d, flags=%#x, mtu=%d, len=%d\n",
2370 __func__, dlci, pcb->state, pcb->flags,
2371 pcb->mtu, m0->m_pkthdr.len);
2373 error = EMSGSIZE;
2374 } else if (m0->m_pkthdr.len > sbspace(&pcb->so->so_rcv)) {
2377 * This is really bad. Receive queue on socket does
2378 * not have enough space for the packet. We do not
2379 * have any other choice but drop the packet.
2382 NG_BTSOCKET_RFCOMM_ERR(
2383 "%s: Not enough space in socket receive queue. Dropping UIH for dlci=%d, " \
2384 "state=%d, flags=%#x, len=%d, space=%ld\n",
2385 __func__, dlci, pcb->state, pcb->flags,
2386 m0->m_pkthdr.len, sbspace(&pcb->so->so_rcv));
2388 error = ENOBUFS;
2389 } else {
2390 /* Append packet to the socket receive queue */
2391 sbappend(&pcb->so->so_rcv, m0);
2392 m0 = NULL;
2394 sorwakeup(pcb->so);
2397 drop1:
2398 mtx_unlock(&pcb->pcb_mtx);
2399 drop:
2400 NG_FREE_M(m0); /* checks for != NULL */
2402 return (error);
2403 } /* ng_btsocket_rfcomm_receive_uih */
2406 * Process RFCOMM MCC command (Multiplexor)
2408 * From TS 07.10 spec
2410 * "5.4.3.1 Information Data
2412 * ...The frames (UIH) sent by the initiating station have the C/R bit set
2413 * to 1 and those sent by the responding station have the C/R bit set to 0..."
2415 * "5.4.6.2 Operating procedures
2417 * Messages always exist in pairs; a command message and a corresponding
2418 * response message. If the C/R bit is set to 1 the message is a command,
2419 * if it is set to 0 the message is a response...
2421 * ...
2423 * NOTE: Notice that when UIH frames are used to convey information on DLCI 0
2424 * there are at least two different fields that contain a C/R bit, and the
2425 * bits are set of different form. The C/R bit in the Type field shall be set
2426 * as it is stated above, while the C/R bit in the Address field (see subclause
2427 * 5.2.1.2) shall be set as it is described in subclause 5.4.3.1."
2430 static int
2431 ng_btsocket_rfcomm_receive_mcc(ng_btsocket_rfcomm_session_p s, struct mbuf *m0)
2433 struct rfcomm_mcc_hdr *hdr = NULL;
2434 u_int8_t cr, type, length;
2436 mtx_assert(&s->session_mtx, MA_OWNED);
2439 * We can access data directly in the first mbuf, because we have
2440 * m_pullup()'ed mbuf chain in ng_btsocket_rfcomm_receive_frame().
2441 * All MCC commands should fit into single mbuf (except probably TEST).
2444 hdr = mtod(m0, struct rfcomm_mcc_hdr *);
2445 cr = RFCOMM_CR(hdr->type);
2446 type = RFCOMM_MCC_TYPE(hdr->type);
2447 length = RFCOMM_MCC_LENGTH(hdr->length);
2449 /* Check MCC frame length */
2450 if (sizeof(*hdr) + length != m0->m_pkthdr.len) {
2451 NG_BTSOCKET_RFCOMM_ERR(
2452 "%s: Invalid MCC frame length=%d, len=%d\n",
2453 __func__, length, m0->m_pkthdr.len);
2454 NG_FREE_M(m0);
2456 return (EMSGSIZE);
2459 switch (type) {
2460 case RFCOMM_MCC_TEST:
2461 return (ng_btsocket_rfcomm_receive_test(s, m0));
2462 /* NOT REACHED */
2464 case RFCOMM_MCC_FCON:
2465 case RFCOMM_MCC_FCOFF:
2466 return (ng_btsocket_rfcomm_receive_fc(s, m0));
2467 /* NOT REACHED */
2469 case RFCOMM_MCC_MSC:
2470 return (ng_btsocket_rfcomm_receive_msc(s, m0));
2471 /* NOT REACHED */
2473 case RFCOMM_MCC_RPN:
2474 return (ng_btsocket_rfcomm_receive_rpn(s, m0));
2475 /* NOT REACHED */
2477 case RFCOMM_MCC_RLS:
2478 return (ng_btsocket_rfcomm_receive_rls(s, m0));
2479 /* NOT REACHED */
2481 case RFCOMM_MCC_PN:
2482 return (ng_btsocket_rfcomm_receive_pn(s, m0));
2483 /* NOT REACHED */
2485 case RFCOMM_MCC_NSC:
2486 NG_BTSOCKET_RFCOMM_ERR(
2487 "%s: Got MCC NSC, type=%#x, cr=%d, length=%d, session state=%d, flags=%#x, " \
2488 "mtu=%d, len=%d\n", __func__, RFCOMM_MCC_TYPE(*((u_int8_t *)(hdr + 1))), cr,
2489 length, s->state, s->flags, s->mtu, m0->m_pkthdr.len);
2490 NG_FREE_M(m0);
2491 break;
2493 default:
2494 NG_BTSOCKET_RFCOMM_ERR(
2495 "%s: Got unknown MCC, type=%#x, cr=%d, length=%d, session state=%d, " \
2496 "flags=%#x, mtu=%d, len=%d\n",
2497 __func__, type, cr, length, s->state, s->flags,
2498 s->mtu, m0->m_pkthdr.len);
2500 /* Reuse mbuf to send NSC */
2501 hdr = mtod(m0, struct rfcomm_mcc_hdr *);
2502 m0->m_pkthdr.len = m0->m_len = sizeof(*hdr);
2504 /* Create MCC NSC header */
2505 hdr->type = RFCOMM_MKMCC_TYPE(0, RFCOMM_MCC_NSC);
2506 hdr->length = RFCOMM_MKLEN8(1);
2508 /* Put back MCC command type we did not like */
2509 m0->m_data[m0->m_len] = RFCOMM_MKMCC_TYPE(cr, type);
2510 m0->m_pkthdr.len ++;
2511 m0->m_len ++;
2513 /* Send UIH frame */
2514 return (ng_btsocket_rfcomm_send_uih(s,
2515 RFCOMM_MKADDRESS(INITIATOR(s), 0), 0, 0, m0));
2516 /* NOT REACHED */
2519 return (0);
2520 } /* ng_btsocket_rfcomm_receive_mcc */
2523 * Receive RFCOMM TEST MCC command
2526 static int
2527 ng_btsocket_rfcomm_receive_test(ng_btsocket_rfcomm_session_p s, struct mbuf *m0)
2529 struct rfcomm_mcc_hdr *hdr = mtod(m0, struct rfcomm_mcc_hdr *);
2530 int error = 0;
2532 mtx_assert(&s->session_mtx, MA_OWNED);
2534 NG_BTSOCKET_RFCOMM_INFO(
2535 "%s: Got MCC TEST, cr=%d, length=%d, session state=%d, flags=%#x, mtu=%d, " \
2536 "len=%d\n", __func__, RFCOMM_CR(hdr->type), RFCOMM_MCC_LENGTH(hdr->length),
2537 s->state, s->flags, s->mtu, m0->m_pkthdr.len);
2539 if (RFCOMM_CR(hdr->type)) {
2540 hdr->type = RFCOMM_MKMCC_TYPE(0, RFCOMM_MCC_TEST);
2541 error = ng_btsocket_rfcomm_send_uih(s,
2542 RFCOMM_MKADDRESS(INITIATOR(s), 0), 0, 0, m0);
2543 } else
2544 NG_FREE_M(m0); /* XXX ignore response */
2546 return (error);
2547 } /* ng_btsocket_rfcomm_receive_test */
2550 * Receive RFCOMM FCON/FCOFF MCC command
2553 static int
2554 ng_btsocket_rfcomm_receive_fc(ng_btsocket_rfcomm_session_p s, struct mbuf *m0)
2556 struct rfcomm_mcc_hdr *hdr = mtod(m0, struct rfcomm_mcc_hdr *);
2557 u_int8_t type = RFCOMM_MCC_TYPE(hdr->type);
2558 int error = 0;
2560 mtx_assert(&s->session_mtx, MA_OWNED);
2563 * Turn ON/OFF aggregate flow on the entire session. When remote peer
2564 * asserted flow control no transmission shall occur except on dlci 0
2565 * (control channel).
2568 NG_BTSOCKET_RFCOMM_INFO(
2569 "%s: Got MCC FC%s, cr=%d, length=%d, session state=%d, flags=%#x, mtu=%d, " \
2570 "len=%d\n", __func__, (type == RFCOMM_MCC_FCON)? "ON" : "OFF",
2571 RFCOMM_CR(hdr->type), RFCOMM_MCC_LENGTH(hdr->length),
2572 s->state, s->flags, s->mtu, m0->m_pkthdr.len);
2574 if (RFCOMM_CR(hdr->type)) {
2575 if (type == RFCOMM_MCC_FCON)
2576 s->flags &= ~NG_BTSOCKET_RFCOMM_SESSION_RFC;
2577 else
2578 s->flags |= NG_BTSOCKET_RFCOMM_SESSION_RFC;
2580 hdr->type = RFCOMM_MKMCC_TYPE(0, type);
2581 error = ng_btsocket_rfcomm_send_uih(s,
2582 RFCOMM_MKADDRESS(INITIATOR(s), 0), 0, 0, m0);
2583 } else
2584 NG_FREE_M(m0); /* XXX ignore response */
2586 return (error);
2587 } /* ng_btsocket_rfcomm_receive_fc */
2590 * Receive RFCOMM MSC MCC command
2593 static int
2594 ng_btsocket_rfcomm_receive_msc(ng_btsocket_rfcomm_session_p s, struct mbuf *m0)
2596 struct rfcomm_mcc_hdr *hdr = mtod(m0, struct rfcomm_mcc_hdr*);
2597 struct rfcomm_mcc_msc *msc = (struct rfcomm_mcc_msc *)(hdr+1);
2598 ng_btsocket_rfcomm_pcb_t *pcb = NULL;
2599 int error = 0;
2601 mtx_assert(&s->session_mtx, MA_OWNED);
2603 NG_BTSOCKET_RFCOMM_INFO(
2604 "%s: Got MCC MSC, dlci=%d, cr=%d, length=%d, session state=%d, flags=%#x, " \
2605 "mtu=%d, len=%d\n",
2606 __func__, RFCOMM_DLCI(msc->address), RFCOMM_CR(hdr->type),
2607 RFCOMM_MCC_LENGTH(hdr->length), s->state, s->flags,
2608 s->mtu, m0->m_pkthdr.len);
2610 if (RFCOMM_CR(hdr->type)) {
2611 pcb = ng_btsocket_rfcomm_pcb_by_dlci(s, RFCOMM_DLCI(msc->address));
2612 if (pcb == NULL) {
2613 NG_BTSOCKET_RFCOMM_WARN(
2614 "%s: Got MSC command for non-existing dlci=%d\n",
2615 __func__, RFCOMM_DLCI(msc->address));
2616 NG_FREE_M(m0);
2618 return (ENOENT);
2621 mtx_lock(&pcb->pcb_mtx);
2623 if (pcb->state != NG_BTSOCKET_RFCOMM_DLC_CONNECTING &&
2624 pcb->state != NG_BTSOCKET_RFCOMM_DLC_CONNECTED) {
2625 NG_BTSOCKET_RFCOMM_WARN(
2626 "%s: Got MSC on dlci=%d in invalid state=%d\n",
2627 __func__, RFCOMM_DLCI(msc->address),
2628 pcb->state);
2630 mtx_unlock(&pcb->pcb_mtx);
2631 NG_FREE_M(m0);
2633 return (EINVAL);
2636 pcb->rmodem = msc->modem; /* Update remote port signals */
2638 hdr->type = RFCOMM_MKMCC_TYPE(0, RFCOMM_MCC_MSC);
2639 error = ng_btsocket_rfcomm_send_uih(s,
2640 RFCOMM_MKADDRESS(INITIATOR(s), 0), 0, 0, m0);
2642 #if 0 /* YYY */
2643 /* Send more data from DLC. XXX check for errors? */
2644 if (!(pcb->rmodem & RFCOMM_MODEM_FC) &&
2645 !(pcb->flags & NG_BTSOCKET_RFCOMM_DLC_CFC))
2646 ng_btsocket_rfcomm_pcb_send(pcb, ALOT);
2647 #endif /* YYY */
2649 mtx_unlock(&pcb->pcb_mtx);
2650 } else
2651 NG_FREE_M(m0); /* XXX ignore response */
2653 return (error);
2654 } /* ng_btsocket_rfcomm_receive_msc */
2657 * Receive RFCOMM RPN MCC command
2658 * XXX FIXME do we need htole16/le16toh for RPN param_mask?
2661 static int
2662 ng_btsocket_rfcomm_receive_rpn(ng_btsocket_rfcomm_session_p s, struct mbuf *m0)
2664 struct rfcomm_mcc_hdr *hdr = mtod(m0, struct rfcomm_mcc_hdr *);
2665 struct rfcomm_mcc_rpn *rpn = (struct rfcomm_mcc_rpn *)(hdr + 1);
2666 int error = 0;
2667 u_int16_t param_mask;
2668 u_int8_t bit_rate, data_bits, stop_bits, parity,
2669 flow_control, xon_char, xoff_char;
2671 mtx_assert(&s->session_mtx, MA_OWNED);
2673 NG_BTSOCKET_RFCOMM_INFO(
2674 "%s: Got MCC RPN, dlci=%d, cr=%d, length=%d, session state=%d, flags=%#x, " \
2675 "mtu=%d, len=%d\n",
2676 __func__, RFCOMM_DLCI(rpn->dlci), RFCOMM_CR(hdr->type),
2677 RFCOMM_MCC_LENGTH(hdr->length), s->state, s->flags,
2678 s->mtu, m0->m_pkthdr.len);
2680 if (RFCOMM_CR(hdr->type)) {
2681 param_mask = RFCOMM_RPN_PM_ALL;
2683 if (RFCOMM_MCC_LENGTH(hdr->length) == 1) {
2684 /* Request - return default setting */
2685 bit_rate = RFCOMM_RPN_BR_115200;
2686 data_bits = RFCOMM_RPN_DATA_8;
2687 stop_bits = RFCOMM_RPN_STOP_1;
2688 parity = RFCOMM_RPN_PARITY_NONE;
2689 flow_control = RFCOMM_RPN_FLOW_NONE;
2690 xon_char = RFCOMM_RPN_XON_CHAR;
2691 xoff_char = RFCOMM_RPN_XOFF_CHAR;
2692 } else {
2694 * Ignore/accept bit_rate, 8 bits, 1 stop bit, no
2695 * parity, no flow control lines, default XON/XOFF
2696 * chars.
2699 bit_rate = rpn->bit_rate;
2700 rpn->param_mask = le16toh(rpn->param_mask); /* XXX */
2702 data_bits = RFCOMM_RPN_DATA_BITS(rpn->line_settings);
2703 if (rpn->param_mask & RFCOMM_RPN_PM_DATA &&
2704 data_bits != RFCOMM_RPN_DATA_8) {
2705 data_bits = RFCOMM_RPN_DATA_8;
2706 param_mask ^= RFCOMM_RPN_PM_DATA;
2709 stop_bits = RFCOMM_RPN_STOP_BITS(rpn->line_settings);
2710 if (rpn->param_mask & RFCOMM_RPN_PM_STOP &&
2711 stop_bits != RFCOMM_RPN_STOP_1) {
2712 stop_bits = RFCOMM_RPN_STOP_1;
2713 param_mask ^= RFCOMM_RPN_PM_STOP;
2716 parity = RFCOMM_RPN_PARITY(rpn->line_settings);
2717 if (rpn->param_mask & RFCOMM_RPN_PM_PARITY &&
2718 parity != RFCOMM_RPN_PARITY_NONE) {
2719 parity = RFCOMM_RPN_PARITY_NONE;
2720 param_mask ^= RFCOMM_RPN_PM_PARITY;
2723 flow_control = rpn->flow_control;
2724 if (rpn->param_mask & RFCOMM_RPN_PM_FLOW &&
2725 flow_control != RFCOMM_RPN_FLOW_NONE) {
2726 flow_control = RFCOMM_RPN_FLOW_NONE;
2727 param_mask ^= RFCOMM_RPN_PM_FLOW;
2730 xon_char = rpn->xon_char;
2731 if (rpn->param_mask & RFCOMM_RPN_PM_XON &&
2732 xon_char != RFCOMM_RPN_XON_CHAR) {
2733 xon_char = RFCOMM_RPN_XON_CHAR;
2734 param_mask ^= RFCOMM_RPN_PM_XON;
2737 xoff_char = rpn->xoff_char;
2738 if (rpn->param_mask & RFCOMM_RPN_PM_XOFF &&
2739 xoff_char != RFCOMM_RPN_XOFF_CHAR) {
2740 xoff_char = RFCOMM_RPN_XOFF_CHAR;
2741 param_mask ^= RFCOMM_RPN_PM_XOFF;
2745 rpn->bit_rate = bit_rate;
2746 rpn->line_settings = RFCOMM_MKRPN_LINE_SETTINGS(data_bits,
2747 stop_bits, parity);
2748 rpn->flow_control = flow_control;
2749 rpn->xon_char = xon_char;
2750 rpn->xoff_char = xoff_char;
2751 rpn->param_mask = htole16(param_mask); /* XXX */
2753 m0->m_pkthdr.len = m0->m_len = sizeof(*hdr) + sizeof(*rpn);
2755 hdr->type = RFCOMM_MKMCC_TYPE(0, RFCOMM_MCC_RPN);
2756 error = ng_btsocket_rfcomm_send_uih(s,
2757 RFCOMM_MKADDRESS(INITIATOR(s), 0), 0, 0, m0);
2758 } else
2759 NG_FREE_M(m0); /* XXX ignore response */
2761 return (error);
2762 } /* ng_btsocket_rfcomm_receive_rpn */
2765 * Receive RFCOMM RLS MCC command
2768 static int
2769 ng_btsocket_rfcomm_receive_rls(ng_btsocket_rfcomm_session_p s, struct mbuf *m0)
2771 struct rfcomm_mcc_hdr *hdr = mtod(m0, struct rfcomm_mcc_hdr *);
2772 struct rfcomm_mcc_rls *rls = (struct rfcomm_mcc_rls *)(hdr + 1);
2773 int error = 0;
2775 mtx_assert(&s->session_mtx, MA_OWNED);
2778 * XXX FIXME Do we have to do anything else here? Remote peer tries to
2779 * tell us something about DLCI. Just report what we have received and
2780 * return back received values as required by TS 07.10 spec.
2783 NG_BTSOCKET_RFCOMM_INFO(
2784 "%s: Got MCC RLS, dlci=%d, status=%#x, cr=%d, length=%d, session state=%d, " \
2785 "flags=%#x, mtu=%d, len=%d\n",
2786 __func__, RFCOMM_DLCI(rls->address), rls->status,
2787 RFCOMM_CR(hdr->type), RFCOMM_MCC_LENGTH(hdr->length),
2788 s->state, s->flags, s->mtu, m0->m_pkthdr.len);
2790 if (RFCOMM_CR(hdr->type)) {
2791 if (rls->status & 0x1)
2792 NG_BTSOCKET_RFCOMM_ERR(
2793 "%s: Got RLS dlci=%d, error=%#x\n", __func__, RFCOMM_DLCI(rls->address),
2794 rls->status >> 1);
2796 hdr->type = RFCOMM_MKMCC_TYPE(0, RFCOMM_MCC_RLS);
2797 error = ng_btsocket_rfcomm_send_uih(s,
2798 RFCOMM_MKADDRESS(INITIATOR(s), 0), 0, 0, m0);
2799 } else
2800 NG_FREE_M(m0); /* XXX ignore responses */
2802 return (error);
2803 } /* ng_btsocket_rfcomm_receive_rls */
2806 * Receive RFCOMM PN MCC command
2809 static int
2810 ng_btsocket_rfcomm_receive_pn(ng_btsocket_rfcomm_session_p s, struct mbuf *m0)
2812 struct rfcomm_mcc_hdr *hdr = mtod(m0, struct rfcomm_mcc_hdr*);
2813 struct rfcomm_mcc_pn *pn = (struct rfcomm_mcc_pn *)(hdr+1);
2814 ng_btsocket_rfcomm_pcb_t *pcb = NULL;
2815 int error = 0;
2817 mtx_assert(&s->session_mtx, MA_OWNED);
2819 NG_BTSOCKET_RFCOMM_INFO(
2820 "%s: Got MCC PN, dlci=%d, cr=%d, length=%d, flow_control=%#x, priority=%d, " \
2821 "ack_timer=%d, mtu=%d, max_retrans=%d, credits=%d, session state=%d, " \
2822 "flags=%#x, session mtu=%d, len=%d\n",
2823 __func__, pn->dlci, RFCOMM_CR(hdr->type),
2824 RFCOMM_MCC_LENGTH(hdr->length), pn->flow_control, pn->priority,
2825 pn->ack_timer, le16toh(pn->mtu), pn->max_retrans, pn->credits,
2826 s->state, s->flags, s->mtu, m0->m_pkthdr.len);
2828 if (pn->dlci == 0) {
2829 NG_BTSOCKET_RFCOMM_ERR("%s: Zero dlci in MCC PN\n", __func__);
2830 NG_FREE_M(m0);
2832 return (EINVAL);
2835 /* Check if we have this dlci */
2836 pcb = ng_btsocket_rfcomm_pcb_by_dlci(s, pn->dlci);
2837 if (pcb != NULL) {
2838 mtx_lock(&pcb->pcb_mtx);
2840 if (RFCOMM_CR(hdr->type)) {
2841 /* PN Request */
2842 ng_btsocket_rfcomm_set_pn(pcb, 1, pn->flow_control,
2843 pn->credits, pn->mtu);
2845 if (pcb->flags & NG_BTSOCKET_RFCOMM_DLC_CFC) {
2846 pn->flow_control = 0xe0;
2847 pn->credits = RFCOMM_DEFAULT_CREDITS;
2848 } else {
2849 pn->flow_control = 0;
2850 pn->credits = 0;
2853 hdr->type = RFCOMM_MKMCC_TYPE(0, RFCOMM_MCC_PN);
2854 error = ng_btsocket_rfcomm_send_uih(s,
2855 RFCOMM_MKADDRESS(INITIATOR(s), 0),
2856 0, 0, m0);
2857 } else {
2858 /* PN Response - proceed with SABM. Timeout still set */
2859 if (pcb->state == NG_BTSOCKET_RFCOMM_DLC_CONFIGURING) {
2860 ng_btsocket_rfcomm_set_pn(pcb, 0,
2861 pn->flow_control, pn->credits, pn->mtu);
2863 pcb->state = NG_BTSOCKET_RFCOMM_DLC_CONNECTING;
2864 error = ng_btsocket_rfcomm_send_command(s,
2865 RFCOMM_FRAME_SABM, pn->dlci);
2866 } else
2867 NG_BTSOCKET_RFCOMM_WARN(
2868 "%s: Got PN response for dlci=%d in invalid state=%d\n",
2869 __func__, pn->dlci, pcb->state);
2871 NG_FREE_M(m0);
2874 mtx_unlock(&pcb->pcb_mtx);
2875 } else if (RFCOMM_CR(hdr->type)) {
2876 /* PN request to non-existing dlci - incomming connection */
2877 pcb = ng_btsocket_rfcomm_connect_ind(s,
2878 RFCOMM_SRVCHANNEL(pn->dlci));
2879 if (pcb != NULL) {
2880 mtx_lock(&pcb->pcb_mtx);
2882 pcb->dlci = pn->dlci;
2884 ng_btsocket_rfcomm_set_pn(pcb, 1, pn->flow_control,
2885 pn->credits, pn->mtu);
2887 if (pcb->flags & NG_BTSOCKET_RFCOMM_DLC_CFC) {
2888 pn->flow_control = 0xe0;
2889 pn->credits = RFCOMM_DEFAULT_CREDITS;
2890 } else {
2891 pn->flow_control = 0;
2892 pn->credits = 0;
2895 hdr->type = RFCOMM_MKMCC_TYPE(0, RFCOMM_MCC_PN);
2896 error = ng_btsocket_rfcomm_send_uih(s,
2897 RFCOMM_MKADDRESS(INITIATOR(s), 0),
2898 0, 0, m0);
2900 if (error == 0) {
2901 ng_btsocket_rfcomm_timeout(pcb);
2902 pcb->state = NG_BTSOCKET_RFCOMM_DLC_CONNECTING;
2903 soisconnecting(pcb->so);
2904 } else
2905 ng_btsocket_rfcomm_pcb_kill(pcb, error);
2907 mtx_unlock(&pcb->pcb_mtx);
2908 } else {
2909 /* Nobody is listen()ing on this channel */
2910 error = ng_btsocket_rfcomm_send_command(s,
2911 RFCOMM_FRAME_DM, pn->dlci);
2912 NG_FREE_M(m0);
2914 } else
2915 NG_FREE_M(m0); /* XXX ignore response to non-existing dlci */
2917 return (error);
2918 } /* ng_btsocket_rfcomm_receive_pn */
2921 * Set PN parameters for dlci. Caller must hold pcb->pcb_mtx.
2923 * From Bluetooth spec.
2925 * "... The CL1 - CL4 field is completely redefined. (In TS07.10 this defines
2926 * the convergence layer to use, which is not applicable to RFCOMM. In RFCOMM,
2927 * in Bluetooth versions up to 1.0B, this field was forced to 0).
2929 * In the PN request sent prior to a DLC establishment, this field must contain
2930 * the value 15 (0xF), indicating support of credit based flow control in the
2931 * sender. See Table 5.3 below. If the PN response contains any other value
2932 * than 14 (0xE) in this field, it is inferred that the peer RFCOMM entity is
2933 * not supporting the credit based flow control feature. (This is only possible
2934 * if the peer RFCOMM implementation is only conforming to Bluetooth version
2935 * 1.0B.) If a PN request is sent on an already open DLC, then this field must
2936 * contain the value zero; it is not possible to set initial credits more
2937 * than once per DLC activation. A responding implementation must set this
2938 * field in the PN response to 14 (0xE), if (and only if) the value in the PN
2939 * request was 15..."
2942 static void
2943 ng_btsocket_rfcomm_set_pn(ng_btsocket_rfcomm_pcb_p pcb, u_int8_t cr,
2944 u_int8_t flow_control, u_int8_t credits, u_int16_t mtu)
2946 mtx_assert(&pcb->pcb_mtx, MA_OWNED);
2948 pcb->mtu = le16toh(mtu);
2950 if (cr) {
2951 if (flow_control == 0xf0) {
2952 pcb->flags |= NG_BTSOCKET_RFCOMM_DLC_CFC;
2953 pcb->tx_cred = credits;
2954 } else {
2955 pcb->flags &= ~NG_BTSOCKET_RFCOMM_DLC_CFC;
2956 pcb->tx_cred = 0;
2958 } else {
2959 if (flow_control == 0xe0) {
2960 pcb->flags |= NG_BTSOCKET_RFCOMM_DLC_CFC;
2961 pcb->tx_cred = credits;
2962 } else {
2963 pcb->flags &= ~NG_BTSOCKET_RFCOMM_DLC_CFC;
2964 pcb->tx_cred = 0;
2968 NG_BTSOCKET_RFCOMM_INFO(
2969 "%s: cr=%d, dlci=%d, state=%d, flags=%#x, mtu=%d, rx_cred=%d, tx_cred=%d\n",
2970 __func__, cr, pcb->dlci, pcb->state, pcb->flags, pcb->mtu,
2971 pcb->rx_cred, pcb->tx_cred);
2972 } /* ng_btsocket_rfcomm_set_pn */
2975 * Send RFCOMM SABM/DISC/UA/DM frames. Caller must hold s->session_mtx
2978 static int
2979 ng_btsocket_rfcomm_send_command(ng_btsocket_rfcomm_session_p s,
2980 u_int8_t type, u_int8_t dlci)
2982 struct rfcomm_cmd_hdr *hdr = NULL;
2983 struct mbuf *m = NULL;
2984 int cr;
2986 mtx_assert(&s->session_mtx, MA_OWNED);
2988 NG_BTSOCKET_RFCOMM_INFO(
2989 "%s: Sending command type %#x, session state=%d, flags=%#x, mtu=%d, dlci=%d\n",
2990 __func__, type, s->state, s->flags, s->mtu, dlci);
2992 switch (type) {
2993 case RFCOMM_FRAME_SABM:
2994 case RFCOMM_FRAME_DISC:
2995 cr = INITIATOR(s);
2996 break;
2998 case RFCOMM_FRAME_UA:
2999 case RFCOMM_FRAME_DM:
3000 cr = !INITIATOR(s);
3001 break;
3003 default:
3004 panic("%s: Invalid frame type=%#x\n", __func__, type);
3005 return (EINVAL);
3006 /* NOT REACHED */
3009 MGETHDR(m, M_DONTWAIT, MT_DATA);
3010 if (m == NULL)
3011 return (ENOBUFS);
3013 m->m_pkthdr.len = m->m_len = sizeof(*hdr);
3015 hdr = mtod(m, struct rfcomm_cmd_hdr *);
3016 hdr->address = RFCOMM_MKADDRESS(cr, dlci);
3017 hdr->control = RFCOMM_MKCONTROL(type, 1);
3018 hdr->length = RFCOMM_MKLEN8(0);
3019 hdr->fcs = ng_btsocket_rfcomm_fcs3((u_int8_t *) hdr);
3021 NG_BT_MBUFQ_ENQUEUE(&s->outq, m);
3023 return (0);
3024 } /* ng_btsocket_rfcomm_send_command */
3027 * Send RFCOMM UIH frame. Caller must hold s->session_mtx
3030 static int
3031 ng_btsocket_rfcomm_send_uih(ng_btsocket_rfcomm_session_p s, u_int8_t address,
3032 u_int8_t pf, u_int8_t credits, struct mbuf *data)
3034 struct rfcomm_frame_hdr *hdr = NULL;
3035 struct mbuf *m = NULL, *mcrc = NULL;
3036 u_int16_t length;
3038 mtx_assert(&s->session_mtx, MA_OWNED);
3040 MGETHDR(m, M_DONTWAIT, MT_DATA);
3041 if (m == NULL) {
3042 NG_FREE_M(data);
3043 return (ENOBUFS);
3045 m->m_pkthdr.len = m->m_len = sizeof(*hdr);
3047 MGET(mcrc, M_DONTWAIT, MT_DATA);
3048 if (mcrc == NULL) {
3049 NG_FREE_M(data);
3050 return (ENOBUFS);
3052 mcrc->m_len = 1;
3054 /* Fill UIH frame header */
3055 hdr = mtod(m, struct rfcomm_frame_hdr *);
3056 hdr->address = address;
3057 hdr->control = RFCOMM_MKCONTROL(RFCOMM_FRAME_UIH, pf);
3059 /* Calculate FCS */
3060 mcrc->m_data[0] = ng_btsocket_rfcomm_fcs2((u_int8_t *) hdr);
3062 /* Put length back */
3063 length = (data != NULL)? data->m_pkthdr.len : 0;
3064 if (length > 127) {
3065 u_int16_t l = htole16(RFCOMM_MKLEN16(length));
3067 bcopy(&l, &hdr->length, sizeof(l));
3068 m->m_pkthdr.len ++;
3069 m->m_len ++;
3070 } else
3071 hdr->length = RFCOMM_MKLEN8(length);
3073 if (pf) {
3074 m->m_data[m->m_len] = credits;
3075 m->m_pkthdr.len ++;
3076 m->m_len ++;
3079 /* Add payload */
3080 if (data != NULL) {
3081 m_cat(m, data);
3082 m->m_pkthdr.len += length;
3085 /* Put FCS back */
3086 m_cat(m, mcrc);
3087 m->m_pkthdr.len ++;
3089 NG_BTSOCKET_RFCOMM_INFO(
3090 "%s: Sending UIH state=%d, flags=%#x, address=%d, length=%d, pf=%d, " \
3091 "credits=%d, len=%d\n",
3092 __func__, s->state, s->flags, address, length, pf, credits,
3093 m->m_pkthdr.len);
3095 NG_BT_MBUFQ_ENQUEUE(&s->outq, m);
3097 return (0);
3098 } /* ng_btsocket_rfcomm_send_uih */
3101 * Send MSC request. Caller must hold pcb->pcb_mtx and pcb->session->session_mtx
3104 static int
3105 ng_btsocket_rfcomm_send_msc(ng_btsocket_rfcomm_pcb_p pcb)
3107 struct mbuf *m = NULL;
3108 struct rfcomm_mcc_hdr *hdr = NULL;
3109 struct rfcomm_mcc_msc *msc = NULL;
3111 mtx_assert(&pcb->session->session_mtx, MA_OWNED);
3112 mtx_assert(&pcb->pcb_mtx, MA_OWNED);
3114 MGETHDR(m, M_DONTWAIT, MT_DATA);
3115 if (m == NULL)
3116 return (ENOBUFS);
3118 m->m_pkthdr.len = m->m_len = sizeof(*hdr) + sizeof(*msc);
3120 hdr = mtod(m, struct rfcomm_mcc_hdr *);
3121 msc = (struct rfcomm_mcc_msc *)(hdr + 1);
3123 hdr->type = RFCOMM_MKMCC_TYPE(1, RFCOMM_MCC_MSC);
3124 hdr->length = RFCOMM_MKLEN8(sizeof(*msc));
3126 msc->address = RFCOMM_MKADDRESS(1, pcb->dlci);
3127 msc->modem = pcb->lmodem;
3129 NG_BTSOCKET_RFCOMM_INFO(
3130 "%s: Sending MSC dlci=%d, state=%d, flags=%#x, address=%d, modem=%#x\n",
3131 __func__, pcb->dlci, pcb->state, pcb->flags, msc->address,
3132 msc->modem);
3134 return (ng_btsocket_rfcomm_send_uih(pcb->session,
3135 RFCOMM_MKADDRESS(INITIATOR(pcb->session), 0), 0, 0, m));
3136 } /* ng_btsocket_rfcomm_send_msc */
3139 * Send PN request. Caller must hold pcb->pcb_mtx and pcb->session->session_mtx
3142 static int
3143 ng_btsocket_rfcomm_send_pn(ng_btsocket_rfcomm_pcb_p pcb)
3145 struct mbuf *m = NULL;
3146 struct rfcomm_mcc_hdr *hdr = NULL;
3147 struct rfcomm_mcc_pn *pn = NULL;
3149 mtx_assert(&pcb->session->session_mtx, MA_OWNED);
3150 mtx_assert(&pcb->pcb_mtx, MA_OWNED);
3152 MGETHDR(m, M_DONTWAIT, MT_DATA);
3153 if (m == NULL)
3154 return (ENOBUFS);
3156 m->m_pkthdr.len = m->m_len = sizeof(*hdr) + sizeof(*pn);
3158 hdr = mtod(m, struct rfcomm_mcc_hdr *);
3159 pn = (struct rfcomm_mcc_pn *)(hdr + 1);
3161 hdr->type = RFCOMM_MKMCC_TYPE(1, RFCOMM_MCC_PN);
3162 hdr->length = RFCOMM_MKLEN8(sizeof(*pn));
3164 pn->dlci = pcb->dlci;
3167 * Set default DLCI priority as described in GSM 07.10
3168 * (ETSI TS 101 369) clause 5.6 page 42
3171 pn->priority = (pcb->dlci < 56)? (((pcb->dlci >> 3) << 3) + 7) : 61;
3172 pn->ack_timer = 0;
3173 pn->mtu = htole16(pcb->mtu);
3174 pn->max_retrans = 0;
3176 if (pcb->flags & NG_BTSOCKET_RFCOMM_DLC_CFC) {
3177 pn->flow_control = 0xf0;
3178 pn->credits = pcb->rx_cred;
3179 } else {
3180 pn->flow_control = 0;
3181 pn->credits = 0;
3184 NG_BTSOCKET_RFCOMM_INFO(
3185 "%s: Sending PN dlci=%d, state=%d, flags=%#x, mtu=%d, flow_control=%#x, " \
3186 "credits=%d\n", __func__, pcb->dlci, pcb->state, pcb->flags, pcb->mtu,
3187 pn->flow_control, pn->credits);
3189 return (ng_btsocket_rfcomm_send_uih(pcb->session,
3190 RFCOMM_MKADDRESS(INITIATOR(pcb->session), 0), 0, 0, m));
3191 } /* ng_btsocket_rfcomm_send_pn */
3194 * Calculate and send credits based on available space in receive buffer
3197 static int
3198 ng_btsocket_rfcomm_send_credits(ng_btsocket_rfcomm_pcb_p pcb)
3200 int error = 0;
3201 u_int8_t credits;
3203 mtx_assert(&pcb->pcb_mtx, MA_OWNED);
3204 mtx_assert(&pcb->session->session_mtx, MA_OWNED);
3206 NG_BTSOCKET_RFCOMM_INFO(
3207 "%s: Sending more credits, dlci=%d, state=%d, flags=%#x, mtu=%d, " \
3208 "space=%ld, tx_cred=%d, rx_cred=%d\n",
3209 __func__, pcb->dlci, pcb->state, pcb->flags, pcb->mtu,
3210 sbspace(&pcb->so->so_rcv), pcb->tx_cred, pcb->rx_cred);
3212 credits = sbspace(&pcb->so->so_rcv) / pcb->mtu;
3213 if (credits > 0) {
3214 if (pcb->rx_cred + credits > RFCOMM_MAX_CREDITS)
3215 credits = RFCOMM_MAX_CREDITS - pcb->rx_cred;
3217 error = ng_btsocket_rfcomm_send_uih(
3218 pcb->session,
3219 RFCOMM_MKADDRESS(INITIATOR(pcb->session),
3220 pcb->dlci), 1, credits, NULL);
3221 if (error == 0) {
3222 pcb->rx_cred += credits;
3224 NG_BTSOCKET_RFCOMM_INFO(
3225 "%s: Gave remote side %d more credits, dlci=%d, state=%d, flags=%#x, " \
3226 "rx_cred=%d, tx_cred=%d\n", __func__, credits, pcb->dlci, pcb->state,
3227 pcb->flags, pcb->rx_cred, pcb->tx_cred);
3228 } else
3229 NG_BTSOCKET_RFCOMM_ERR(
3230 "%s: Could not send credits, error=%d, dlci=%d, state=%d, flags=%#x, " \
3231 "mtu=%d, space=%ld, tx_cred=%d, rx_cred=%d\n",
3232 __func__, error, pcb->dlci, pcb->state,
3233 pcb->flags, pcb->mtu, sbspace(&pcb->so->so_rcv),
3234 pcb->tx_cred, pcb->rx_cred);
3237 return (error);
3238 } /* ng_btsocket_rfcomm_send_credits */
3240 /*****************************************************************************
3241 *****************************************************************************
3242 ** RFCOMM DLCs
3243 *****************************************************************************
3244 *****************************************************************************/
3247 * Send data from socket send buffer
3248 * Caller must hold pcb->pcb_mtx and pcb->session->session_mtx
3251 static int
3252 ng_btsocket_rfcomm_pcb_send(ng_btsocket_rfcomm_pcb_p pcb, int limit)
3254 struct mbuf *m = NULL;
3255 int sent, length, error;
3257 mtx_assert(&pcb->session->session_mtx, MA_OWNED);
3258 mtx_assert(&pcb->pcb_mtx, MA_OWNED);
3260 if (pcb->flags & NG_BTSOCKET_RFCOMM_DLC_CFC)
3261 limit = min(limit, pcb->tx_cred);
3262 else if (!(pcb->rmodem & RFCOMM_MODEM_FC))
3263 limit = min(limit, RFCOMM_MAX_CREDITS); /* XXX ??? */
3264 else
3265 limit = 0;
3267 if (limit == 0) {
3268 NG_BTSOCKET_RFCOMM_INFO(
3269 "%s: Could not send - remote flow control asserted, dlci=%d, flags=%#x, " \
3270 "rmodem=%#x, tx_cred=%d\n",
3271 __func__, pcb->dlci, pcb->flags, pcb->rmodem,
3272 pcb->tx_cred);
3274 return (0);
3277 for (error = 0, sent = 0; sent < limit; sent ++) {
3278 length = min(pcb->mtu, pcb->so->so_snd.sb_cc);
3279 if (length == 0)
3280 break;
3282 /* Get the chunk from the socket's send buffer */
3283 m = ng_btsocket_rfcomm_prepare_packet(&pcb->so->so_snd, length);
3284 if (m == NULL) {
3285 error = ENOBUFS;
3286 break;
3289 sbdrop(&pcb->so->so_snd, length);
3291 error = ng_btsocket_rfcomm_send_uih(pcb->session,
3292 RFCOMM_MKADDRESS(INITIATOR(pcb->session),
3293 pcb->dlci), 0, 0, m);
3294 if (error != 0)
3295 break;
3298 if (pcb->flags & NG_BTSOCKET_RFCOMM_DLC_CFC)
3299 pcb->tx_cred -= sent;
3301 if (error == 0 && sent > 0) {
3302 pcb->flags &= ~NG_BTSOCKET_RFCOMM_DLC_SENDING;
3303 sowwakeup(pcb->so);
3306 return (error);
3307 } /* ng_btsocket_rfcomm_pcb_send */
3310 * Unlink and disconnect DLC. If ng_btsocket_rfcomm_pcb_kill() returns
3311 * non zero value than socket has no reference and has to be detached.
3312 * Caller must hold pcb->pcb_mtx and pcb->session->session_mtx
3315 static void
3316 ng_btsocket_rfcomm_pcb_kill(ng_btsocket_rfcomm_pcb_p pcb, int error)
3318 ng_btsocket_rfcomm_session_p s = pcb->session;
3320 NG_BTSOCKET_RFCOMM_INFO(
3321 "%s: Killing DLC, so=%p, dlci=%d, state=%d, flags=%#x, error=%d\n",
3322 __func__, pcb->so, pcb->dlci, pcb->state, pcb->flags, error);
3324 if (pcb->session == NULL)
3325 panic("%s: DLC without session, pcb=%p, state=%d, flags=%#x\n",
3326 __func__, pcb, pcb->state, pcb->flags);
3328 mtx_assert(&pcb->session->session_mtx, MA_OWNED);
3329 mtx_assert(&pcb->pcb_mtx, MA_OWNED);
3331 if (pcb->flags & NG_BTSOCKET_RFCOMM_DLC_TIMO)
3332 ng_btsocket_rfcomm_untimeout(pcb);
3334 /* Detach DLC from the session. Does not matter which state DLC in */
3335 LIST_REMOVE(pcb, session_next);
3336 pcb->session = NULL;
3338 /* Change DLC state and wakeup all sleepers */
3339 pcb->state = NG_BTSOCKET_RFCOMM_DLC_CLOSED;
3340 pcb->so->so_error = error;
3341 soisdisconnected(pcb->so);
3342 wakeup(&pcb->state);
3344 /* Check if we have any DLCs left on the session */
3345 if (LIST_EMPTY(&s->dlcs) && INITIATOR(s)) {
3346 NG_BTSOCKET_RFCOMM_INFO(
3347 "%s: Disconnecting session, state=%d, flags=%#x, mtu=%d\n",
3348 __func__, s->state, s->flags, s->mtu);
3350 switch (s->state) {
3351 case NG_BTSOCKET_RFCOMM_SESSION_CLOSED:
3352 case NG_BTSOCKET_RFCOMM_SESSION_DISCONNECTING:
3354 * Do not have to do anything here. We can get here
3355 * when L2CAP connection was terminated or we have
3356 * received DISC on multiplexor channel
3358 break;
3360 case NG_BTSOCKET_RFCOMM_SESSION_OPEN:
3361 /* Send DISC on multiplexor channel */
3362 error = ng_btsocket_rfcomm_send_command(s,
3363 RFCOMM_FRAME_DISC, 0);
3364 if (error == 0) {
3365 s->state = NG_BTSOCKET_RFCOMM_SESSION_DISCONNECTING;
3366 break;
3368 /* FALL THROUGH */
3370 case NG_BTSOCKET_RFCOMM_SESSION_CONNECTING:
3371 case NG_BTSOCKET_RFCOMM_SESSION_CONNECTED:
3372 s->state = NG_BTSOCKET_RFCOMM_SESSION_CLOSED;
3373 break;
3375 /* case NG_BTSOCKET_RFCOMM_SESSION_LISTENING: */
3376 default:
3377 panic("%s: Invalid session state=%d, flags=%#x\n",
3378 __func__, s->state, s->flags);
3379 break;
3382 ng_btsocket_rfcomm_task_wakeup();
3384 } /* ng_btsocket_rfcomm_pcb_kill */
3387 * Look for given dlci for given RFCOMM session. Caller must hold s->session_mtx
3390 static ng_btsocket_rfcomm_pcb_p
3391 ng_btsocket_rfcomm_pcb_by_dlci(ng_btsocket_rfcomm_session_p s, int dlci)
3393 ng_btsocket_rfcomm_pcb_p pcb = NULL;
3395 mtx_assert(&s->session_mtx, MA_OWNED);
3397 LIST_FOREACH(pcb, &s->dlcs, session_next)
3398 if (pcb->dlci == dlci)
3399 break;
3401 return (pcb);
3402 } /* ng_btsocket_rfcomm_pcb_by_dlci */
3405 * Look for socket that listens on given src address and given channel
3408 static ng_btsocket_rfcomm_pcb_p
3409 ng_btsocket_rfcomm_pcb_listener(bdaddr_p src, int channel)
3411 ng_btsocket_rfcomm_pcb_p pcb = NULL, pcb1 = NULL;
3413 mtx_lock(&ng_btsocket_rfcomm_sockets_mtx);
3415 LIST_FOREACH(pcb, &ng_btsocket_rfcomm_sockets, next) {
3416 if (pcb->channel != channel ||
3417 !(pcb->so->so_options & SO_ACCEPTCONN))
3418 continue;
3420 if (bcmp(&pcb->src, src, sizeof(*src)) == 0)
3421 break;
3423 if (bcmp(&pcb->src, NG_HCI_BDADDR_ANY, sizeof(bdaddr_t)) == 0)
3424 pcb1 = pcb;
3427 mtx_unlock(&ng_btsocket_rfcomm_sockets_mtx);
3429 return ((pcb != NULL)? pcb : pcb1);
3430 } /* ng_btsocket_rfcomm_pcb_listener */
3432 /*****************************************************************************
3433 *****************************************************************************
3434 ** Misc. functions
3435 *****************************************************************************
3436 *****************************************************************************/
3439 * Set timeout. Caller MUST hold pcb_mtx
3442 static void
3443 ng_btsocket_rfcomm_timeout(ng_btsocket_rfcomm_pcb_p pcb)
3445 mtx_assert(&pcb->pcb_mtx, MA_OWNED);
3447 if (!(pcb->flags & NG_BTSOCKET_RFCOMM_DLC_TIMO)) {
3448 pcb->flags |= NG_BTSOCKET_RFCOMM_DLC_TIMO;
3449 pcb->flags &= ~NG_BTSOCKET_RFCOMM_DLC_TIMEDOUT;
3450 pcb->timo = timeout(ng_btsocket_rfcomm_process_timeout, pcb,
3451 ng_btsocket_rfcomm_timo * hz);
3452 } else
3453 panic("%s: Duplicated socket timeout?!\n", __func__);
3454 } /* ng_btsocket_rfcomm_timeout */
3457 * Unset pcb timeout. Caller MUST hold pcb_mtx
3460 static void
3461 ng_btsocket_rfcomm_untimeout(ng_btsocket_rfcomm_pcb_p pcb)
3463 mtx_assert(&pcb->pcb_mtx, MA_OWNED);
3465 if (pcb->flags & NG_BTSOCKET_RFCOMM_DLC_TIMO) {
3466 untimeout(ng_btsocket_rfcomm_process_timeout, pcb, pcb->timo);
3467 pcb->flags &= ~NG_BTSOCKET_RFCOMM_DLC_TIMO;
3468 pcb->flags &= ~NG_BTSOCKET_RFCOMM_DLC_TIMEDOUT;
3469 } else
3470 panic("%s: No socket timeout?!\n", __func__);
3471 } /* ng_btsocket_rfcomm_timeout */
3474 * Process pcb timeout
3477 static void
3478 ng_btsocket_rfcomm_process_timeout(void *xpcb)
3480 ng_btsocket_rfcomm_pcb_p pcb = (ng_btsocket_rfcomm_pcb_p) xpcb;
3482 mtx_lock(&pcb->pcb_mtx);
3484 NG_BTSOCKET_RFCOMM_INFO(
3485 "%s: Timeout, so=%p, dlci=%d, state=%d, flags=%#x\n",
3486 __func__, pcb->so, pcb->dlci, pcb->state, pcb->flags);
3488 pcb->flags &= ~NG_BTSOCKET_RFCOMM_DLC_TIMO;
3489 pcb->flags |= NG_BTSOCKET_RFCOMM_DLC_TIMEDOUT;
3491 switch (pcb->state) {
3492 case NG_BTSOCKET_RFCOMM_DLC_CONFIGURING:
3493 case NG_BTSOCKET_RFCOMM_DLC_CONNECTING:
3494 pcb->state = NG_BTSOCKET_RFCOMM_DLC_DISCONNECTING;
3495 break;
3497 case NG_BTSOCKET_RFCOMM_DLC_W4_CONNECT:
3498 case NG_BTSOCKET_RFCOMM_DLC_DISCONNECTING:
3499 break;
3501 default:
3502 panic(
3503 "%s: DLC timeout in invalid state, dlci=%d, state=%d, flags=%#x\n",
3504 __func__, pcb->dlci, pcb->state, pcb->flags);
3505 break;
3508 ng_btsocket_rfcomm_task_wakeup();
3510 mtx_unlock(&pcb->pcb_mtx);
3511 } /* ng_btsocket_rfcomm_process_timeout */
3514 * Get up to length bytes from the socket buffer
3517 static struct mbuf *
3518 ng_btsocket_rfcomm_prepare_packet(struct sockbuf *sb, int length)
3520 struct mbuf *top = NULL, *m = NULL, *n = NULL, *nextpkt = NULL;
3521 int mlen, noff, len;
3523 MGETHDR(top, M_DONTWAIT, MT_DATA);
3524 if (top == NULL)
3525 return (NULL);
3527 top->m_pkthdr.len = length;
3528 top->m_len = 0;
3529 mlen = MHLEN;
3531 m = top;
3532 n = sb->sb_mb;
3533 nextpkt = n->m_nextpkt;
3534 noff = 0;
3536 while (length > 0 && n != NULL) {
3537 len = min(mlen - m->m_len, n->m_len - noff);
3538 if (len > length)
3539 len = length;
3541 bcopy(mtod(n, caddr_t)+noff, mtod(m, caddr_t)+m->m_len, len);
3542 m->m_len += len;
3543 noff += len;
3544 length -= len;
3546 if (length > 0 && m->m_len == mlen) {
3547 MGET(m->m_next, M_DONTWAIT, MT_DATA);
3548 if (m->m_next == NULL) {
3549 NG_FREE_M(top);
3550 return (NULL);
3553 m = m->m_next;
3554 m->m_len = 0;
3555 mlen = MLEN;
3558 if (noff == n->m_len) {
3559 noff = 0;
3560 n = n->m_next;
3562 if (n == NULL)
3563 n = nextpkt;
3565 nextpkt = (n != NULL)? n->m_nextpkt : NULL;
3569 if (length < 0)
3570 panic("%s: length=%d\n", __func__, length);
3571 if (length > 0 && n == NULL)
3572 panic("%s: bogus length=%d, n=%p\n", __func__, length, n);
3574 return (top);
3575 } /* ng_btsocket_rfcomm_prepare_packet */