6 * Copyright (c) 2001-2003 Maksim Yevmenkin <m_evmenkin@yahoo.com>
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
19 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
22 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * $Id: ng_btsocket_rfcomm.c,v 1.28 2003/09/14 23:29:06 max Exp $
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/kernel.h>
43 #include <sys/malloc.h>
46 #include <sys/protosw.h>
47 #include <sys/queue.h>
48 #include <sys/socket.h>
49 #include <sys/socketvar.h>
50 #include <sys/sysctl.h>
51 #include <sys/taskqueue.h>
53 #include <sys/msgport2.h>
54 #include <sys/fcntl.h>
55 #include <sys/socketvar2.h>
56 #include <net/netmsg2.h>
57 #include <netgraph7/ng_message.h>
58 #include <netgraph7/netgraph.h>
59 #include <netgraph7/bluetooth/include/ng_bluetooth.h>
60 #include <netgraph7/bluetooth/include/ng_hci.h>
61 #include <netgraph7/bluetooth/include/ng_l2cap.h>
62 #include <netgraph7/bluetooth/include/ng_btsocket.h>
63 #include <netgraph7/bluetooth/include/ng_btsocket_l2cap.h>
64 #include <netgraph7/bluetooth/include/ng_btsocket_rfcomm.h>
67 #ifdef NG_SEPARATE_MALLOC
68 MALLOC_DEFINE(M_NETGRAPH_BTSOCKET_RFCOMM, "netgraph_btsocks_rfcomm",
69 "Netgraph Bluetooth RFCOMM sockets");
71 #define M_NETGRAPH_BTSOCKET_RFCOMM M_NETGRAPH
72 #endif /* NG_SEPARATE_MALLOC */
75 #define NG_BTSOCKET_RFCOMM_INFO \
76 if (ng_btsocket_rfcomm_debug_level >= NG_BTSOCKET_INFO_LEVEL) \
79 #define NG_BTSOCKET_RFCOMM_WARN \
80 if (ng_btsocket_rfcomm_debug_level >= NG_BTSOCKET_WARN_LEVEL) \
83 #define NG_BTSOCKET_RFCOMM_ERR \
84 if (ng_btsocket_rfcomm_debug_level >= NG_BTSOCKET_ERR_LEVEL) \
87 #define NG_BTSOCKET_RFCOMM_ALERT \
88 if (ng_btsocket_rfcomm_debug_level >= NG_BTSOCKET_ALERT_LEVEL) \
93 /* Local prototypes */
94 static void ng_btsocket_rfcomm_upcall
95 (struct socket *so, void *arg, int waitflag);
96 static void ng_btsocket_rfcomm_sessions_task
97 (void *ctx, int pending);
98 static void ng_btsocket_rfcomm_session_task
99 (ng_btsocket_rfcomm_session_p s);
100 #define ng_btsocket_rfcomm_task_wakeup() \
101 taskqueue_enqueue(taskqueue_swi, &ng_btsocket_rfcomm_task)
103 static ng_btsocket_rfcomm_pcb_p ng_btsocket_rfcomm_connect_ind
104 (ng_btsocket_rfcomm_session_p s, int channel);
105 static void ng_btsocket_rfcomm_connect_cfm
106 (ng_btsocket_rfcomm_session_p s);
108 static int ng_btsocket_rfcomm_session_create
109 (ng_btsocket_rfcomm_session_p *sp, struct socket *l2so,
110 bdaddr_p src, bdaddr_p dst, struct thread *td);
111 static int ng_btsocket_rfcomm_session_accept
112 (ng_btsocket_rfcomm_session_p s0);
113 static int ng_btsocket_rfcomm_session_connect
114 (ng_btsocket_rfcomm_session_p s);
115 static int ng_btsocket_rfcomm_session_receive
116 (ng_btsocket_rfcomm_session_p s);
117 static int ng_btsocket_rfcomm_session_send
118 (ng_btsocket_rfcomm_session_p s);
119 static void ng_btsocket_rfcomm_session_clean
120 (ng_btsocket_rfcomm_session_p s);
121 static void ng_btsocket_rfcomm_session_process_pcb
122 (ng_btsocket_rfcomm_session_p s);
123 static ng_btsocket_rfcomm_session_p ng_btsocket_rfcomm_session_by_addr
124 (bdaddr_p src, bdaddr_p dst);
126 static int ng_btsocket_rfcomm_receive_frame
127 (ng_btsocket_rfcomm_session_p s, struct mbuf *m0);
128 static int ng_btsocket_rfcomm_receive_sabm
129 (ng_btsocket_rfcomm_session_p s, int dlci);
130 static int ng_btsocket_rfcomm_receive_disc
131 (ng_btsocket_rfcomm_session_p s, int dlci);
132 static int ng_btsocket_rfcomm_receive_ua
133 (ng_btsocket_rfcomm_session_p s, int dlci);
134 static int ng_btsocket_rfcomm_receive_dm
135 (ng_btsocket_rfcomm_session_p s, int dlci);
136 static int ng_btsocket_rfcomm_receive_uih
137 (ng_btsocket_rfcomm_session_p s, int dlci, int pf, struct mbuf *m0);
138 static int ng_btsocket_rfcomm_receive_mcc
139 (ng_btsocket_rfcomm_session_p s, struct mbuf *m0);
140 static int ng_btsocket_rfcomm_receive_test
141 (ng_btsocket_rfcomm_session_p s, struct mbuf *m0);
142 static int ng_btsocket_rfcomm_receive_fc
143 (ng_btsocket_rfcomm_session_p s, struct mbuf *m0);
144 static int ng_btsocket_rfcomm_receive_msc
145 (ng_btsocket_rfcomm_session_p s, struct mbuf *m0);
146 static int ng_btsocket_rfcomm_receive_rpn
147 (ng_btsocket_rfcomm_session_p s, struct mbuf *m0);
148 static int ng_btsocket_rfcomm_receive_rls
149 (ng_btsocket_rfcomm_session_p s, struct mbuf *m0);
150 static int ng_btsocket_rfcomm_receive_pn
151 (ng_btsocket_rfcomm_session_p s, struct mbuf *m0);
152 static void ng_btsocket_rfcomm_set_pn
153 (ng_btsocket_rfcomm_pcb_p pcb, u_int8_t cr, u_int8_t flow_control,
154 u_int8_t credits, u_int16_t mtu);
156 static int ng_btsocket_rfcomm_send_command
157 (ng_btsocket_rfcomm_session_p s, u_int8_t type, u_int8_t dlci);
158 static int ng_btsocket_rfcomm_send_uih
159 (ng_btsocket_rfcomm_session_p s, u_int8_t address, u_int8_t pf,
160 u_int8_t credits, struct mbuf *data);
161 static int ng_btsocket_rfcomm_send_msc
162 (ng_btsocket_rfcomm_pcb_p pcb);
163 static int ng_btsocket_rfcomm_send_pn
164 (ng_btsocket_rfcomm_pcb_p pcb);
165 static int ng_btsocket_rfcomm_send_credits
166 (ng_btsocket_rfcomm_pcb_p pcb);
168 static int ng_btsocket_rfcomm_pcb_send
169 (ng_btsocket_rfcomm_pcb_p pcb, int limit);
170 static void ng_btsocket_rfcomm_pcb_kill
171 (ng_btsocket_rfcomm_pcb_p pcb, int error);
172 static ng_btsocket_rfcomm_pcb_p ng_btsocket_rfcomm_pcb_by_dlci
173 (ng_btsocket_rfcomm_session_p s, int dlci);
174 static ng_btsocket_rfcomm_pcb_p ng_btsocket_rfcomm_pcb_listener
175 (bdaddr_p src, int channel);
177 static void ng_btsocket_rfcomm_timeout
178 (ng_btsocket_rfcomm_pcb_p pcb);
179 static void ng_btsocket_rfcomm_untimeout
180 (ng_btsocket_rfcomm_pcb_p pcb);
181 static void ng_btsocket_rfcomm_process_timeout
184 static struct mbuf * ng_btsocket_rfcomm_prepare_packet
185 (struct sockbuf *sb, int length);
188 extern int ifqmaxlen;
189 static u_int32_t ng_btsocket_rfcomm_debug_level;
190 static u_int32_t ng_btsocket_rfcomm_timo;
191 struct task ng_btsocket_rfcomm_task;
192 static LIST_HEAD(, ng_btsocket_rfcomm_session) ng_btsocket_rfcomm_sessions;
193 static struct lock ng_btsocket_rfcomm_sessions_lock;
194 static LIST_HEAD(, ng_btsocket_rfcomm_pcb) ng_btsocket_rfcomm_sockets;
195 static struct lock ng_btsocket_rfcomm_sockets_lock;
198 SYSCTL_DECL(_net_bluetooth_rfcomm_sockets);
199 SYSCTL_NODE(_net_bluetooth_rfcomm_sockets, OID_AUTO, stream, CTLFLAG_RW,
200 0, "Bluetooth STREAM RFCOMM sockets family");
201 SYSCTL_INT(_net_bluetooth_rfcomm_sockets_stream, OID_AUTO, debug_level,
203 &ng_btsocket_rfcomm_debug_level, NG_BTSOCKET_INFO_LEVEL,
204 "Bluetooth STREAM RFCOMM sockets debug level");
205 SYSCTL_INT(_net_bluetooth_rfcomm_sockets_stream, OID_AUTO, timeout,
207 &ng_btsocket_rfcomm_timo, 60,
208 "Bluetooth STREAM RFCOMM sockets timeout");
210 /*****************************************************************************
211 *****************************************************************************
213 *****************************************************************************
214 *****************************************************************************/
216 static u_int8_t ng_btsocket_rfcomm_crc_table[256] = {
217 0x00, 0x91, 0xe3, 0x72, 0x07, 0x96, 0xe4, 0x75,
218 0x0e, 0x9f, 0xed, 0x7c, 0x09, 0x98, 0xea, 0x7b,
219 0x1c, 0x8d, 0xff, 0x6e, 0x1b, 0x8a, 0xf8, 0x69,
220 0x12, 0x83, 0xf1, 0x60, 0x15, 0x84, 0xf6, 0x67,
222 0x38, 0xa9, 0xdb, 0x4a, 0x3f, 0xae, 0xdc, 0x4d,
223 0x36, 0xa7, 0xd5, 0x44, 0x31, 0xa0, 0xd2, 0x43,
224 0x24, 0xb5, 0xc7, 0x56, 0x23, 0xb2, 0xc0, 0x51,
225 0x2a, 0xbb, 0xc9, 0x58, 0x2d, 0xbc, 0xce, 0x5f,
227 0x70, 0xe1, 0x93, 0x02, 0x77, 0xe6, 0x94, 0x05,
228 0x7e, 0xef, 0x9d, 0x0c, 0x79, 0xe8, 0x9a, 0x0b,
229 0x6c, 0xfd, 0x8f, 0x1e, 0x6b, 0xfa, 0x88, 0x19,
230 0x62, 0xf3, 0x81, 0x10, 0x65, 0xf4, 0x86, 0x17,
232 0x48, 0xd9, 0xab, 0x3a, 0x4f, 0xde, 0xac, 0x3d,
233 0x46, 0xd7, 0xa5, 0x34, 0x41, 0xd0, 0xa2, 0x33,
234 0x54, 0xc5, 0xb7, 0x26, 0x53, 0xc2, 0xb0, 0x21,
235 0x5a, 0xcb, 0xb9, 0x28, 0x5d, 0xcc, 0xbe, 0x2f,
237 0xe0, 0x71, 0x03, 0x92, 0xe7, 0x76, 0x04, 0x95,
238 0xee, 0x7f, 0x0d, 0x9c, 0xe9, 0x78, 0x0a, 0x9b,
239 0xfc, 0x6d, 0x1f, 0x8e, 0xfb, 0x6a, 0x18, 0x89,
240 0xf2, 0x63, 0x11, 0x80, 0xf5, 0x64, 0x16, 0x87,
242 0xd8, 0x49, 0x3b, 0xaa, 0xdf, 0x4e, 0x3c, 0xad,
243 0xd6, 0x47, 0x35, 0xa4, 0xd1, 0x40, 0x32, 0xa3,
244 0xc4, 0x55, 0x27, 0xb6, 0xc3, 0x52, 0x20, 0xb1,
245 0xca, 0x5b, 0x29, 0xb8, 0xcd, 0x5c, 0x2e, 0xbf,
247 0x90, 0x01, 0x73, 0xe2, 0x97, 0x06, 0x74, 0xe5,
248 0x9e, 0x0f, 0x7d, 0xec, 0x99, 0x08, 0x7a, 0xeb,
249 0x8c, 0x1d, 0x6f, 0xfe, 0x8b, 0x1a, 0x68, 0xf9,
250 0x82, 0x13, 0x61, 0xf0, 0x85, 0x14, 0x66, 0xf7,
252 0xa8, 0x39, 0x4b, 0xda, 0xaf, 0x3e, 0x4c, 0xdd,
253 0xa6, 0x37, 0x45, 0xd4, 0xa1, 0x30, 0x42, 0xd3,
254 0xb4, 0x25, 0x57, 0xc6, 0xb3, 0x22, 0x50, 0xc1,
255 0xba, 0x2b, 0x59, 0xc8, 0xbd, 0x2c, 0x5e, 0xcf
260 ng_btsocket_rfcomm_crc(u_int8_t *data, int length)
265 crc = ng_btsocket_rfcomm_crc_table[crc ^ *data++];
268 } /* ng_btsocket_rfcomm_crc */
272 ng_btsocket_rfcomm_fcs2(u_int8_t *data)
274 return (0xff - ng_btsocket_rfcomm_crc(data, 2));
275 } /* ng_btsocket_rfcomm_fcs2 */
279 ng_btsocket_rfcomm_fcs3(u_int8_t *data)
281 return (0xff - ng_btsocket_rfcomm_crc(data, 3));
282 } /* ng_btsocket_rfcomm_fcs3 */
287 * From Bluetooth spec
289 * "... In 07.10, the frame check sequence (FCS) is calculated on different
290 * sets of fields for different frame types. These are the fields that the
291 * FCS are calculated on:
293 * For SABM, DISC, UA, DM frames: on Address, Control and length field.
294 * For UIH frames: on Address and Control field.
296 * (This is stated here for clarification, and to set the standard for RFCOMM;
297 * the fields included in FCS calculation have actually changed in version
298 * 7.0.0 of TS 07.10, but RFCOMM will not change the FCS calculation scheme
299 * from the one above.) ..."
303 ng_btsocket_rfcomm_check_fcs(u_int8_t *data, int type, u_int8_t fcs)
305 if (type != RFCOMM_FRAME_UIH)
306 return (ng_btsocket_rfcomm_fcs3(data) != fcs);
308 return (ng_btsocket_rfcomm_fcs2(data) != fcs);
309 } /* ng_btsocket_rfcomm_check_fcs */
311 /*****************************************************************************
312 *****************************************************************************
314 *****************************************************************************
315 *****************************************************************************/
318 * Initialize everything
322 ng_btsocket_rfcomm_init(void)
324 ng_btsocket_rfcomm_debug_level = NG_BTSOCKET_WARN_LEVEL;
325 ng_btsocket_rfcomm_timo = 60;
328 TASK_INIT(&ng_btsocket_rfcomm_task, 0,
329 ng_btsocket_rfcomm_sessions_task, NULL);
331 /* RFCOMM sessions list */
332 LIST_INIT(&ng_btsocket_rfcomm_sessions);
333 lockinit(&ng_btsocket_rfcomm_sessions_lock,
334 "btsocks_rfcomm_sessions_lock", 0, 0);
336 /* RFCOMM sockets list */
337 LIST_INIT(&ng_btsocket_rfcomm_sockets);
338 lockinit(&ng_btsocket_rfcomm_sockets_lock,
339 "btsocks_rfcomm_sockets_lock", 0, 0);
340 } /* ng_btsocket_rfcomm_init */
343 * Abort connection on socket
347 ng_btsocket_rfcomm_abort(netmsg_t msg)
349 struct socket *so = msg->abort.base.nm_so;
351 so->so_error = ECONNABORTED;
352 ng_btsocket_rfcomm_disconnect(msg);
353 } /* ng_btsocket_rfcomm_abort */
357 ng_btsocket_rfcomm_close(struct socket *so)
360 (void)ng_btsocket_rfcomm_disconnect(so);
361 } /* ng_btsocket_rfcomm_close */
365 * Accept connection on socket. Nothing to do here, socket must be connected
366 * and ready, so just return peer address and be done with it.
370 ng_btsocket_rfcomm_accept(netmsg_t msg)
372 ng_btsocket_rfcomm_peeraddr(msg);
373 } /* ng_btsocket_rfcomm_accept */
376 * Create and attach new socket
380 ng_btsocket_rfcomm_attach(netmsg_t msg)
382 struct socket *so = msg->attach.base.nm_so;
383 ng_btsocket_rfcomm_pcb_p pcb = so2rfcomm_pcb(so);
386 /* Check socket and protocol */
387 if (so->so_type != SOCK_STREAM) {
388 error = ESOCKTNOSUPPORT;
392 #if 0 /* XXX sonewconn() calls "pru_attach" with proto == 0 */
394 if (proto != BLUETOOTH_PROTO_RFCOMM) {
395 error = EPROTONOSUPPORT;
405 /* Reserve send and receive space if it is not reserved yet */
406 if ((so->so_snd.ssb_hiwat == 0) || (so->so_rcv.ssb_hiwat == 0)) {
407 error = soreserve(so, NG_BTSOCKET_RFCOMM_SENDSPACE,
408 NG_BTSOCKET_RFCOMM_RECVSPACE, NULL);
413 /* Allocate the PCB */
414 pcb = kmalloc(sizeof(*pcb), M_NETGRAPH_BTSOCKET_RFCOMM,
415 M_WAITOK | M_NULLOK | M_ZERO);
421 /* Link the PCB and the socket */
422 so->so_pcb = (caddr_t) pcb;
426 pcb->state = NG_BTSOCKET_RFCOMM_DLC_CLOSED;
427 pcb->flags = NG_BTSOCKET_RFCOMM_DLC_CFC;
430 pcb->rmodem = (RFCOMM_MODEM_RTC | RFCOMM_MODEM_RTR | RFCOMM_MODEM_DV);
432 pcb->mtu = RFCOMM_DEFAULT_MTU;
434 pcb->rx_cred = RFCOMM_DEFAULT_CREDITS;
436 lockinit(&pcb->pcb_lock, "btsocks_rfcomm_pcb_lock", 0, 0);
437 callout_init_mp(&pcb->timo);
439 /* Add the PCB to the list */
440 lockmgr(&ng_btsocket_rfcomm_sockets_lock, LK_EXCLUSIVE);
441 LIST_INSERT_HEAD(&ng_btsocket_rfcomm_sockets, pcb, next);
442 lockmgr(&ng_btsocket_rfcomm_sockets_lock, LK_RELEASE);
445 lwkt_replymsg(&msg->attach.base.lmsg, error);
446 } /* ng_btsocket_rfcomm_attach */
453 ng_btsocket_rfcomm_bind(netmsg_t msg)
455 struct socket *so = msg->bind.base.nm_so;
456 struct sockaddr *nam = msg->bind.nm_nam;
457 ng_btsocket_rfcomm_pcb_t *pcb = so2rfcomm_pcb(so), *pcb1;
458 struct sockaddr_rfcomm *sa = (struct sockaddr_rfcomm *) nam;
471 if (sa->rfcomm_family != AF_BLUETOOTH) {
472 error = EAFNOSUPPORT;
475 if (sa->rfcomm_len != sizeof(*sa)) {
479 if (sa->rfcomm_channel > 30) {
484 lockmgr(&pcb->pcb_lock, LK_EXCLUSIVE);
486 if (sa->rfcomm_channel != 0) {
487 lockmgr(&ng_btsocket_rfcomm_sockets_lock, LK_EXCLUSIVE);
489 LIST_FOREACH(pcb1, &ng_btsocket_rfcomm_sockets, next) {
490 if (pcb1->channel == sa->rfcomm_channel &&
491 bcmp(&pcb1->src, &sa->rfcomm_bdaddr,
492 sizeof(pcb1->src)) == 0) {
493 lockmgr(&ng_btsocket_rfcomm_sockets_lock, LK_RELEASE);
494 lockmgr(&pcb->pcb_lock, LK_RELEASE);
501 lockmgr(&ng_btsocket_rfcomm_sockets_lock, LK_RELEASE);
504 bcopy(&sa->rfcomm_bdaddr, &pcb->src, sizeof(pcb->src));
505 pcb->channel = sa->rfcomm_channel;
507 lockmgr(&pcb->pcb_lock, LK_RELEASE);
510 lwkt_replymsg(&msg->bind.base.lmsg, error);
511 } /* ng_btsocket_rfcomm_bind */
518 ng_btsocket_rfcomm_connect(netmsg_t msg)
520 struct socket *so = msg->connect.base.nm_so;
521 struct sockaddr *nam = msg->connect.nm_nam;
522 struct thread *td = msg->connect.nm_td;
523 ng_btsocket_rfcomm_pcb_t *pcb = so2rfcomm_pcb(so);
524 struct sockaddr_rfcomm *sa = (struct sockaddr_rfcomm *) nam;
525 ng_btsocket_rfcomm_session_t *s = NULL;
526 struct socket *l2so = NULL;
539 if (sa->rfcomm_family != AF_BLUETOOTH) {
540 error = EAFNOSUPPORT;
543 if (sa->rfcomm_len != sizeof(*sa)) {
547 if (sa->rfcomm_channel > 30) {
551 if (sa->rfcomm_channel == 0 ||
552 bcmp(&sa->rfcomm_bdaddr, NG_HCI_BDADDR_ANY, sizeof(bdaddr_t)) == 0) {
553 error = EDESTADDRREQ;
558 * XXX FIXME - This is FUBAR. socreate() will call soalloc(1), i.e.
559 * soalloc() is allowed to sleep in MALLOC. This creates "could sleep"
560 * WITNESS warnings. To work around this problem we will create L2CAP
561 * socket first and then check if we actually need it. Note that we
562 * will not check for errors in socreate() because if we failed to
563 * create L2CAP socket at this point we still might have already open
567 error = socreate(PF_BLUETOOTH, &l2so, SOCK_SEQPACKET,
568 BLUETOOTH_PROTO_L2CAP, td);
571 * Look for session between "pcb->src" and "sa->rfcomm_bdaddr" (dst)
574 lockmgr(&ng_btsocket_rfcomm_sessions_lock, LK_EXCLUSIVE);
576 s = ng_btsocket_rfcomm_session_by_addr(&pcb->src, &sa->rfcomm_bdaddr);
579 * We need to create new RFCOMM session. Check if we have L2CAP
580 * socket. If l2so == NULL then error has the error code from
585 lockmgr(&ng_btsocket_rfcomm_sessions_lock, LK_RELEASE);
589 error = ng_btsocket_rfcomm_session_create(&s, l2so,
590 &pcb->src, &sa->rfcomm_bdaddr, td);
592 lockmgr(&ng_btsocket_rfcomm_sessions_lock, LK_RELEASE);
593 soclose(l2so, FNONBLOCK);
597 } else if (l2so != NULL)
598 soclose(l2so, FNONBLOCK); /* we don't need new L2CAP socket */
601 * Check if we already have the same DLCI the the same session
604 lockmgr(&s->session_lock, LK_EXCLUSIVE);
605 lockmgr(&pcb->pcb_lock, LK_EXCLUSIVE);
607 dlci = RFCOMM_MKDLCI(!INITIATOR(s), sa->rfcomm_channel);
609 if (ng_btsocket_rfcomm_pcb_by_dlci(s, dlci) != NULL) {
610 lockmgr(&pcb->pcb_lock, LK_RELEASE);
611 lockmgr(&s->session_lock, LK_RELEASE);
612 lockmgr(&ng_btsocket_rfcomm_sessions_lock, LK_RELEASE);
619 * Check session state and if its not acceptable then refuse connection
623 case NG_BTSOCKET_RFCOMM_SESSION_CONNECTING:
624 case NG_BTSOCKET_RFCOMM_SESSION_CONNECTED:
625 case NG_BTSOCKET_RFCOMM_SESSION_OPEN:
627 * Update destination address and channel and attach
631 bcopy(&sa->rfcomm_bdaddr, &pcb->dst, sizeof(pcb->dst));
632 pcb->channel = sa->rfcomm_channel;
635 LIST_INSERT_HEAD(&s->dlcs, pcb, session_next);
638 ng_btsocket_rfcomm_timeout(pcb);
639 soisconnecting(pcb->so);
641 if (s->state == NG_BTSOCKET_RFCOMM_SESSION_OPEN) {
643 bcopy(&so2l2cap_pcb(s->l2so)->src, &pcb->src,
646 pcb->state = NG_BTSOCKET_RFCOMM_DLC_CONFIGURING;
648 error = ng_btsocket_rfcomm_send_pn(pcb);
650 error = ng_btsocket_rfcomm_task_wakeup();
652 pcb->state = NG_BTSOCKET_RFCOMM_DLC_W4_CONNECT;
660 lockmgr(&pcb->pcb_lock, LK_RELEASE);
661 lockmgr(&s->session_lock, LK_RELEASE);
662 lockmgr(&ng_btsocket_rfcomm_sessions_lock, LK_RELEASE);
665 lwkt_replymsg(&msg->connect.base.lmsg, error);
666 } /* ng_btsocket_rfcomm_connect */
669 * Process ioctl's calls on socket.
670 * XXX FIXME this should provide interface to the RFCOMM multiplexor channel
674 ng_btsocket_rfcomm_control(netmsg_t msg)
676 lwkt_replymsg(&msg->control.base.lmsg, EINVAL);
677 } /* ng_btsocket_rfcomm_control */
680 * Process getsockopt/setsockopt system calls
684 ng_btsocket_rfcomm_ctloutput(netmsg_t msg)
686 struct socket *so = msg->ctloutput.base.nm_so;
687 struct sockopt *sopt = msg->ctloutput.nm_sopt;
688 ng_btsocket_rfcomm_pcb_p pcb = so2rfcomm_pcb(so);
689 struct ng_btsocket_rfcomm_fc_info fcinfo;
696 if (sopt->sopt_level != SOL_RFCOMM)
699 lockmgr(&pcb->pcb_lock, LK_EXCLUSIVE);
701 switch (sopt->sopt_dir) {
703 switch (sopt->sopt_name) {
705 error = sooptcopyout(sopt, &pcb->mtu, sizeof(pcb->mtu));
708 case SO_RFCOMM_FC_INFO:
709 fcinfo.lmodem = pcb->lmodem;
710 fcinfo.rmodem = pcb->rmodem;
711 fcinfo.tx_cred = pcb->tx_cred;
712 fcinfo.rx_cred = pcb->rx_cred;
713 fcinfo.cfc = (pcb->flags & NG_BTSOCKET_RFCOMM_DLC_CFC)?
717 error = sooptcopyout(sopt, &fcinfo, sizeof(fcinfo));
727 switch (sopt->sopt_name) {
739 lockmgr(&pcb->pcb_lock, LK_RELEASE);
742 lwkt_replymsg(&msg->ctloutput.base.lmsg, error);
743 } /* ng_btsocket_rfcomm_ctloutput */
746 * Detach and destroy socket
750 ng_btsocket_rfcomm_detach(netmsg_t msg)
752 struct socket *so = msg->detach.base.nm_so;
753 ng_btsocket_rfcomm_pcb_p pcb = so2rfcomm_pcb(so);
756 KASSERT(pcb != NULL, ("ng_btsocket_rfcomm_detach: pcb == NULL"));
758 lockmgr(&pcb->pcb_lock, LK_EXCLUSIVE);
762 switch (pcb->state) {
763 case NG_BTSOCKET_RFCOMM_DLC_W4_CONNECT:
764 case NG_BTSOCKET_RFCOMM_DLC_CONFIGURING:
765 case NG_BTSOCKET_RFCOMM_DLC_CONNECTING:
766 case NG_BTSOCKET_RFCOMM_DLC_CONNECTED:
767 /* XXX What to do with pending request? */
768 if (pcb->flags & NG_BTSOCKET_RFCOMM_DLC_TIMO)
769 ng_btsocket_rfcomm_untimeout(pcb);
771 if (pcb->state == NG_BTSOCKET_RFCOMM_DLC_W4_CONNECT)
772 pcb->flags |= NG_BTSOCKET_RFCOMM_DLC_DETACHED;
774 pcb->state = NG_BTSOCKET_RFCOMM_DLC_DISCONNECTING;
776 ng_btsocket_rfcomm_task_wakeup();
779 case NG_BTSOCKET_RFCOMM_DLC_DISCONNECTING:
780 ng_btsocket_rfcomm_task_wakeup();
784 while (pcb->state != NG_BTSOCKET_RFCOMM_DLC_CLOSED)
785 lksleep(&pcb->state, &pcb->pcb_lock, 0, "rf_det", 0);
787 if (pcb->session != NULL)
788 panic("%s: pcb->session != NULL", __func__);
789 if (pcb->flags & NG_BTSOCKET_RFCOMM_DLC_TIMO)
790 panic("%s: timeout on closed DLC, flags=%#x",
791 __func__, pcb->flags);
793 lockmgr(&ng_btsocket_rfcomm_sockets_lock, LK_EXCLUSIVE);
794 LIST_REMOVE(pcb, next);
795 lockmgr(&ng_btsocket_rfcomm_sockets_lock, LK_RELEASE);
797 lockmgr(&pcb->pcb_lock, LK_RELEASE);
799 lockuninit(&pcb->pcb_lock);
800 bzero(pcb, sizeof(*pcb));
801 kfree(pcb, M_NETGRAPH_BTSOCKET_RFCOMM);
803 soisdisconnected(so);
804 sofree(so); /* for so_pcb = NULL */
806 lwkt_replymsg(&msg->detach.base.lmsg, error);
807 } /* ng_btsocket_rfcomm_detach */
814 ng_btsocket_rfcomm_disconnect(netmsg_t msg)
816 struct socket *so = msg->disconnect.base.nm_so;
817 ng_btsocket_rfcomm_pcb_p pcb = so2rfcomm_pcb(so);
825 lockmgr(&pcb->pcb_lock, LK_EXCLUSIVE);
827 if (pcb->state == NG_BTSOCKET_RFCOMM_DLC_DISCONNECTING) {
828 lockmgr(&pcb->pcb_lock, LK_RELEASE);
833 /* XXX What to do with pending request? */
834 if (pcb->flags & NG_BTSOCKET_RFCOMM_DLC_TIMO)
835 ng_btsocket_rfcomm_untimeout(pcb);
837 switch (pcb->state) {
838 case NG_BTSOCKET_RFCOMM_DLC_CONFIGURING: /* XXX can we get here? */
839 case NG_BTSOCKET_RFCOMM_DLC_CONNECTING: /* XXX can we get here? */
840 case NG_BTSOCKET_RFCOMM_DLC_CONNECTED:
843 * Just change DLC state and enqueue RFCOMM task. It will
844 * queue and send DISC on the DLC.
847 pcb->state = NG_BTSOCKET_RFCOMM_DLC_DISCONNECTING;
848 soisdisconnecting(so);
850 ng_btsocket_rfcomm_task_wakeup();
853 case NG_BTSOCKET_RFCOMM_DLC_CLOSED:
854 case NG_BTSOCKET_RFCOMM_DLC_W4_CONNECT:
858 panic("%s: Invalid DLC state=%d, flags=%#x",
859 __func__, pcb->state, pcb->flags);
863 lockmgr(&pcb->pcb_lock, LK_RELEASE);
866 lwkt_replymsg(&msg->disconnect.base.lmsg, error);
867 } /* ng_btsocket_rfcomm_disconnect */
870 * Listen on socket. First call to listen() will create listening RFCOMM session
874 ng_btsocket_rfcomm_listen(netmsg_t msg)
876 struct socket *so = msg->listen.base.nm_so;
877 struct thread *td = msg->listen.nm_td;
878 int backlog = msg->listen.nm_flags; /* XXX */
879 ng_btsocket_rfcomm_pcb_p pcb = so2rfcomm_pcb(so), pcb1;
880 ng_btsocket_rfcomm_session_p s = NULL;
881 struct socket *l2so = NULL;
882 int error = 0, socreate_error, usedchannels;
888 if (pcb->channel > 30) {
889 error = EADDRNOTAVAIL;
895 lockmgr(&pcb->pcb_lock, LK_EXCLUSIVE);
897 if (pcb->channel == 0) {
898 lockmgr(&ng_btsocket_rfcomm_sockets_lock, LK_EXCLUSIVE);
900 LIST_FOREACH(pcb1, &ng_btsocket_rfcomm_sockets, next)
901 if (pcb1->channel != 0 &&
902 bcmp(&pcb1->src, &pcb->src, sizeof(pcb->src)) == 0)
903 usedchannels |= (1 << (pcb1->channel - 1));
905 for (pcb->channel = 30; pcb->channel > 0; pcb->channel --)
906 if (!(usedchannels & (1 << (pcb->channel - 1))))
909 if (pcb->channel == 0) {
910 lockmgr(&ng_btsocket_rfcomm_sockets_lock, LK_RELEASE);
911 lockmgr(&pcb->pcb_lock, LK_RELEASE);
913 error = EADDRNOTAVAIL;
917 lockmgr(&ng_btsocket_rfcomm_sockets_lock, LK_RELEASE);
920 lockmgr(&pcb->pcb_lock, LK_RELEASE);
923 * XXX FIXME - This is FUBAR. socreate() will call soalloc(1), i.e.
924 * soalloc() is allowed to sleep in MALLOC. This creates "could sleep"
925 * WITNESS warnings. To work around this problem we will create L2CAP
926 * socket first and then check if we actually need it. Note that we
927 * will not check for errors in socreate() because if we failed to
928 * create L2CAP socket at this point we still might have already open
932 socreate_error = socreate(PF_BLUETOOTH, &l2so, SOCK_SEQPACKET,
933 BLUETOOTH_PROTO_L2CAP, td);
936 * Transition the socket and session into the LISTENING state. Check
937 * for collisions first, as there can only be one.
939 lockmgr(&ng_btsocket_rfcomm_sessions_lock, LK_EXCLUSIVE);
941 (SS_ISCONNECTED | SS_ISCONNECTING | SS_ISDISCONNECTING)) {
946 LIST_FOREACH(s, &ng_btsocket_rfcomm_sessions, next)
947 if (s->state == NG_BTSOCKET_RFCOMM_SESSION_LISTENING)
952 * We need to create default RFCOMM session. Check if we have
953 * L2CAP socket. If l2so == NULL then error has the error code
957 error = socreate_error;
962 * Create default listen RFCOMM session. The default RFCOMM
963 * session will listen on ANY address.
965 * XXX FIXME Note that currently there is no way to adjust MTU
966 * for the default session.
968 error = ng_btsocket_rfcomm_session_create(&s, l2so,
969 NG_HCI_BDADDR_ANY, NULL, td);
974 solisten(so, backlog, td);
977 lockmgr(&ng_btsocket_rfcomm_sessions_lock, LK_RELEASE);
979 * If we still have an l2so reference here, it's unneeded, so release
983 soclose(l2so, FNONBLOCK);
986 lwkt_replymsg(&msg->listen.base.lmsg, error);
987 } /* ng_btsocket_listen */
994 ng_btsocket_rfcomm_peeraddr(netmsg_t msg)
996 struct socket *so = msg->peeraddr.base.nm_so;
997 struct sockaddr **nam = msg->peeraddr.nm_nam;
998 ng_btsocket_rfcomm_pcb_p pcb = so2rfcomm_pcb(so);
999 struct sockaddr_rfcomm sa;
1007 bcopy(&pcb->dst, &sa.rfcomm_bdaddr, sizeof(sa.rfcomm_bdaddr));
1008 sa.rfcomm_channel = pcb->channel;
1009 sa.rfcomm_len = sizeof(sa);
1010 sa.rfcomm_family = AF_BLUETOOTH;
1012 *nam = dup_sockaddr((struct sockaddr *) &sa);
1018 lwkt_replymsg(&msg->peeraddr.base.lmsg, error);
1019 } /* ng_btsocket_rfcomm_peeraddr */
1022 * Send data to socket
1026 ng_btsocket_rfcomm_send(netmsg_t msg)
1028 struct socket *so = msg->send.base.nm_so;
1029 struct mbuf *m = msg->send.nm_m;
1030 struct mbuf *control = msg->send.nm_control;
1031 ng_btsocket_rfcomm_pcb_t *pcb = so2rfcomm_pcb(so);
1034 /* Check socket and input */
1035 if (pcb == NULL || m == NULL || control != NULL) {
1040 lockmgr(&pcb->pcb_lock, LK_EXCLUSIVE);
1042 /* Make sure DLC is connected */
1043 if (pcb->state != NG_BTSOCKET_RFCOMM_DLC_CONNECTED) {
1044 lockmgr(&pcb->pcb_lock, LK_RELEASE);
1049 /* Put the packet on the socket's send queue and wakeup RFCOMM task */
1050 sbappend(&pcb->so->so_snd.sb, m);
1053 if (!(pcb->flags & NG_BTSOCKET_RFCOMM_DLC_SENDING)) {
1054 pcb->flags |= NG_BTSOCKET_RFCOMM_DLC_SENDING;
1055 error = ng_btsocket_rfcomm_task_wakeup();
1058 lockmgr(&pcb->pcb_lock, LK_RELEASE);
1060 NG_FREE_M(m); /* checks for != NULL */
1063 lwkt_replymsg(&msg->send.base.lmsg, error);
1064 } /* ng_btsocket_rfcomm_send */
1067 * Get socket address
1071 ng_btsocket_rfcomm_sockaddr(netmsg_t msg)
1073 struct socket *so = msg->sockaddr.base.nm_so;
1074 struct sockaddr **nam = msg->sockaddr.nm_nam;
1075 ng_btsocket_rfcomm_pcb_p pcb = so2rfcomm_pcb(so);
1076 struct sockaddr_rfcomm sa;
1084 bcopy(&pcb->src, &sa.rfcomm_bdaddr, sizeof(sa.rfcomm_bdaddr));
1085 sa.rfcomm_channel = pcb->channel;
1086 sa.rfcomm_len = sizeof(sa);
1087 sa.rfcomm_family = AF_BLUETOOTH;
1089 *nam = dup_sockaddr((struct sockaddr *) &sa);
1095 lwkt_replymsg(&msg->sockaddr.base.lmsg, error);
1096 } /* ng_btsocket_rfcomm_sockaddr */
1099 * Upcall function for L2CAP sockets. Enqueue RFCOMM task.
1103 ng_btsocket_rfcomm_upcall(struct socket *so, void *arg, int waitflag)
1108 panic("%s: so == NULL", __func__);
1110 if ((error = ng_btsocket_rfcomm_task_wakeup()) != 0)
1111 NG_BTSOCKET_RFCOMM_ALERT(
1112 "%s: Could not enqueue RFCOMM task, error=%d\n", __func__, error);
1113 } /* ng_btsocket_rfcomm_upcall */
1116 * RFCOMM task. Will handle all RFCOMM sessions in one pass.
1117 * XXX FIXME does not scale very well
1121 ng_btsocket_rfcomm_sessions_task(void *ctx, int pending)
1123 ng_btsocket_rfcomm_session_p s = NULL, s_next = NULL;
1125 lockmgr(&ng_btsocket_rfcomm_sessions_lock, LK_EXCLUSIVE);
1127 for (s = LIST_FIRST(&ng_btsocket_rfcomm_sessions); s != NULL; ) {
1128 lockmgr(&s->session_lock, LK_EXCLUSIVE);
1129 s_next = LIST_NEXT(s, next);
1131 ng_btsocket_rfcomm_session_task(s);
1133 if (s->state == NG_BTSOCKET_RFCOMM_SESSION_CLOSED) {
1134 /* Unlink and clean the session */
1135 LIST_REMOVE(s, next);
1137 NG_BT_MBUFQ_DRAIN(&s->outq);
1138 if (!LIST_EMPTY(&s->dlcs))
1139 panic("%s: DLC list is not empty", __func__);
1141 /* Close L2CAP socket */
1142 s->l2so->so_upcallarg = NULL;
1143 s->l2so->so_upcall = NULL;
1144 atomic_clear_int(&s->l2so->so_rcv.ssb_flags, SSB_UPCALL);
1145 atomic_clear_int(&s->l2so->so_snd.ssb_flags, SSB_UPCALL);
1146 soclose(s->l2so, FNONBLOCK);
1148 lockmgr(&s->session_lock, LK_RELEASE);
1150 lockuninit(&s->session_lock);
1151 bzero(s, sizeof(*s));
1152 kfree(s, M_NETGRAPH_BTSOCKET_RFCOMM);
1154 lockmgr(&s->session_lock, LK_RELEASE);
1159 lockmgr(&ng_btsocket_rfcomm_sessions_lock, LK_RELEASE);
1160 } /* ng_btsocket_rfcomm_sessions_task */
1163 * Process RFCOMM session. Will handle all RFCOMM sockets in one pass.
1167 ng_btsocket_rfcomm_session_task(ng_btsocket_rfcomm_session_p s)
1169 KKASSERT(lockowned(&s->session_lock) != 0);
1171 if (s->l2so->so_state & SS_CANTRCVMORE) {
1172 NG_BTSOCKET_RFCOMM_INFO(
1173 "%s: L2CAP connection has been terminated, so=%p, so_state=%#x, " \
1174 "state=%d, flags=%#x\n", __func__, s->l2so, s->l2so->so_state,
1175 s->state, s->flags);
1177 s->state = NG_BTSOCKET_RFCOMM_SESSION_CLOSED;
1178 ng_btsocket_rfcomm_session_clean(s);
1181 /* Now process upcall */
1183 /* Try to accept new L2CAP connection(s) */
1184 case NG_BTSOCKET_RFCOMM_SESSION_LISTENING:
1185 while (ng_btsocket_rfcomm_session_accept(s) == 0)
1189 /* Process the results of the L2CAP connect */
1190 case NG_BTSOCKET_RFCOMM_SESSION_CONNECTING:
1191 ng_btsocket_rfcomm_session_process_pcb(s);
1193 if (ng_btsocket_rfcomm_session_connect(s) != 0) {
1194 s->state = NG_BTSOCKET_RFCOMM_SESSION_CLOSED;
1195 ng_btsocket_rfcomm_session_clean(s);
1199 /* Try to receive/send more data */
1200 case NG_BTSOCKET_RFCOMM_SESSION_CONNECTED:
1201 case NG_BTSOCKET_RFCOMM_SESSION_OPEN:
1202 case NG_BTSOCKET_RFCOMM_SESSION_DISCONNECTING:
1203 ng_btsocket_rfcomm_session_process_pcb(s);
1205 if (ng_btsocket_rfcomm_session_receive(s) != 0) {
1206 s->state = NG_BTSOCKET_RFCOMM_SESSION_CLOSED;
1207 ng_btsocket_rfcomm_session_clean(s);
1208 } else if (ng_btsocket_rfcomm_session_send(s) != 0) {
1209 s->state = NG_BTSOCKET_RFCOMM_SESSION_CLOSED;
1210 ng_btsocket_rfcomm_session_clean(s);
1214 case NG_BTSOCKET_RFCOMM_SESSION_CLOSED:
1218 panic("%s: Invalid session state=%d, flags=%#x",
1219 __func__, s->state, s->flags);
1222 } /* ng_btsocket_rfcomm_session_task */
1225 * Process RFCOMM connection indicator. Caller must hold s->session_mtx
1228 static ng_btsocket_rfcomm_pcb_p
1229 ng_btsocket_rfcomm_connect_ind(ng_btsocket_rfcomm_session_p s, int channel)
1231 ng_btsocket_rfcomm_pcb_p pcb = NULL, pcb1 = NULL;
1232 ng_btsocket_l2cap_pcb_p l2pcb = NULL;
1233 struct socket *so1 = NULL;
1235 KKASSERT(lockowned(&s->session_lock) != 0);
1238 * Try to find RFCOMM socket that listens on given source address
1239 * and channel. This will return the best possible match.
1242 l2pcb = so2l2cap_pcb(s->l2so);
1243 pcb = ng_btsocket_rfcomm_pcb_listener(&l2pcb->src, channel);
1248 * Check the pending connections queue and if we have space then
1249 * create new socket and set proper source and destination address,
1253 lockmgr(&pcb->pcb_lock, LK_EXCLUSIVE);
1255 if (pcb->so->so_qlen <= pcb->so->so_qlimit)
1256 so1 = sonewconn(pcb->so, 0);
1258 lockmgr(&pcb->pcb_lock, LK_RELEASE);
1264 * If we got here than we have created new socket. So complete the
1265 * connection. Set source and destination address from the session.
1268 pcb1 = so2rfcomm_pcb(so1);
1270 panic("%s: pcb1 == NULL", __func__);
1272 lockmgr(&pcb1->pcb_lock, LK_EXCLUSIVE);
1274 bcopy(&l2pcb->src, &pcb1->src, sizeof(pcb1->src));
1275 bcopy(&l2pcb->dst, &pcb1->dst, sizeof(pcb1->dst));
1276 pcb1->channel = channel;
1278 /* Link new DLC to the session. We already hold s->session_mtx */
1279 LIST_INSERT_HEAD(&s->dlcs, pcb1, session_next);
1282 lockmgr(&pcb1->pcb_lock, LK_RELEASE);
1285 } /* ng_btsocket_rfcomm_connect_ind */
1288 * Process RFCOMM connect confirmation. Caller must hold s->session_mtx.
1292 ng_btsocket_rfcomm_connect_cfm(ng_btsocket_rfcomm_session_p s)
1294 ng_btsocket_rfcomm_pcb_p pcb = NULL, pcb_next = NULL;
1297 KKASSERT(lockowned(&s->session_lock) != 0);
1300 * Wake up all waiting sockets and send PN request for each of them.
1301 * Note that timeout already been set in ng_btsocket_rfcomm_connect()
1303 * Note: cannot use LIST_FOREACH because ng_btsocket_rfcomm_pcb_kill
1304 * will unlink DLC from the session
1307 for (pcb = LIST_FIRST(&s->dlcs); pcb != NULL; ) {
1308 lockmgr(&pcb->pcb_lock, LK_EXCLUSIVE);
1309 pcb_next = LIST_NEXT(pcb, session_next);
1311 if (pcb->state == NG_BTSOCKET_RFCOMM_DLC_W4_CONNECT) {
1313 bcopy(&so2l2cap_pcb(s->l2so)->src, &pcb->src,
1316 error = ng_btsocket_rfcomm_send_pn(pcb);
1318 pcb->state = NG_BTSOCKET_RFCOMM_DLC_CONFIGURING;
1320 ng_btsocket_rfcomm_pcb_kill(pcb, error);
1323 lockmgr(&pcb->pcb_lock, LK_RELEASE);
1326 } /* ng_btsocket_rfcomm_connect_cfm */
1328 /*****************************************************************************
1329 *****************************************************************************
1331 *****************************************************************************
1332 *****************************************************************************/
1335 * Create new RFCOMM session. That function WILL NOT take ownership over l2so.
1336 * Caller MUST free l2so if function failed.
1340 ng_btsocket_rfcomm_session_create(ng_btsocket_rfcomm_session_p *sp,
1341 struct socket *l2so, bdaddr_p src, bdaddr_p dst,
1344 ng_btsocket_rfcomm_session_p s = NULL;
1345 struct sockaddr_l2cap l2sa;
1346 struct sockopt l2sopt;
1350 KKASSERT(lockowned(&ng_btsocket_rfcomm_sessions_lock) != 0);
1352 /* Allocate the RFCOMM session */
1353 s = kmalloc(sizeof(*s), M_NETGRAPH_BTSOCKET_RFCOMM,
1354 M_WAITOK | M_NULLOK | M_ZERO);
1359 s->mtu = RFCOMM_DEFAULT_MTU;
1361 s->state = NG_BTSOCKET_RFCOMM_SESSION_CLOSED;
1362 NG_BT_MBUFQ_INIT(&s->outq, ifqmaxlen);
1365 * XXX Mark session mutex as DUPOK to prevent "duplicated lock of
1366 * the same type" message. When accepting new L2CAP connection
1367 * ng_btsocket_rfcomm_session_accept() holds both session mutexes
1368 * for "old" (accepting) session and "new" (created) session.
1371 lockinit(&s->session_lock, "btsocks_rfcomm_session_lock", 0,
1374 LIST_INIT(&s->dlcs);
1376 /* Prepare L2CAP socket */
1377 l2so->so_upcallarg = NULL;
1378 l2so->so_upcall = ng_btsocket_rfcomm_upcall;
1379 atomic_set_int(&l2so->so_rcv.ssb_flags, SSB_UPCALL);
1380 atomic_set_int(&l2so->so_snd.ssb_flags, SSB_UPCALL);
1383 lockmgr(&s->session_lock, LK_EXCLUSIVE);
1386 * "src" == NULL and "dst" == NULL means just create session.
1387 * caller must do the rest
1390 if (src == NULL && dst == NULL)
1394 * Set incoming MTU on L2CAP socket. It is RFCOMM session default MTU
1395 * plus 5 bytes: RFCOMM frame header, one extra byte for length and one
1396 * extra byte for credits.
1399 mtu = s->mtu + sizeof(struct rfcomm_frame_hdr) + 1 + 1;
1401 l2sopt.sopt_dir = SOPT_SET;
1402 l2sopt.sopt_level = SOL_L2CAP;
1403 l2sopt.sopt_name = SO_L2CAP_IMTU;
1404 l2sopt.sopt_val = (void *) &mtu;
1405 l2sopt.sopt_valsize = sizeof(mtu);
1406 l2sopt.sopt_td = NULL;
1408 error = sosetopt(s->l2so, &l2sopt);
1412 /* Bind socket to "src" address */
1413 l2sa.l2cap_len = sizeof(l2sa);
1414 l2sa.l2cap_family = AF_BLUETOOTH;
1415 l2sa.l2cap_psm = (dst == NULL)? htole16(NG_L2CAP_PSM_RFCOMM) : 0;
1416 bcopy(src, &l2sa.l2cap_bdaddr, sizeof(l2sa.l2cap_bdaddr));
1418 error = sobind(s->l2so, (struct sockaddr *) &l2sa, td);
1422 /* If "dst" is not NULL then initiate connect(), otherwise listen() */
1425 s->state = NG_BTSOCKET_RFCOMM_SESSION_LISTENING;
1427 error = solisten(s->l2so, 10, td);
1431 s->flags = NG_BTSOCKET_RFCOMM_SESSION_INITIATOR;
1432 s->state = NG_BTSOCKET_RFCOMM_SESSION_CONNECTING;
1434 l2sa.l2cap_len = sizeof(l2sa);
1435 l2sa.l2cap_family = AF_BLUETOOTH;
1436 l2sa.l2cap_psm = htole16(NG_L2CAP_PSM_RFCOMM);
1437 bcopy(dst, &l2sa.l2cap_bdaddr, sizeof(l2sa.l2cap_bdaddr));
1439 error = soconnect(s->l2so, (struct sockaddr *) &l2sa, td, TRUE);
1445 LIST_INSERT_HEAD(&ng_btsocket_rfcomm_sessions, s, next);
1448 lockmgr(&s->session_lock, LK_RELEASE);
1453 lockmgr(&s->session_lock, LK_RELEASE);
1455 /* Return L2CAP socket back to its original state */
1456 l2so->so_upcallarg = NULL;
1457 l2so->so_upcall = NULL;
1458 atomic_clear_int(&l2so->so_rcv.ssb_flags, SSB_UPCALL);
1459 atomic_clear_int(&l2so->so_snd.ssb_flags, SSB_UPCALL);
1461 lockuninit(&s->session_lock);
1462 bzero(s, sizeof(*s));
1463 kfree(s, M_NETGRAPH_BTSOCKET_RFCOMM);
1466 } /* ng_btsocket_rfcomm_session_create */
1469 * Process accept() on RFCOMM session
1470 * XXX FIXME locking for "l2so"?
1474 ng_btsocket_rfcomm_session_accept(ng_btsocket_rfcomm_session_p s0)
1476 struct socket *l2so = NULL;
1477 struct sockaddr_l2cap *l2sa = NULL;
1478 ng_btsocket_l2cap_pcb_t *l2pcb = NULL;
1479 ng_btsocket_rfcomm_session_p s = NULL;
1482 KKASSERT(lockowned(&ng_btsocket_rfcomm_sessions_lock) != 0);
1483 KKASSERT(lockowned(&s0->session_lock) != 0);
1485 /* Check if there is a complete L2CAP connection in the queue */
1486 if ((error = s0->l2so->so_error) != 0) {
1487 NG_BTSOCKET_RFCOMM_ERR(
1488 "%s: Could not accept connection on L2CAP socket, error=%d\n", __func__, error);
1489 s0->l2so->so_error = 0;
1494 if (TAILQ_EMPTY(&s0->l2so->so_comp)) {
1495 if (s0->l2so->so_state & SS_CANTRCVMORE)
1496 return (ECONNABORTED);
1497 return (EWOULDBLOCK);
1500 /* Accept incoming L2CAP connection */
1501 l2so = TAILQ_FIRST(&s0->l2so->so_comp);
1503 panic("%s: l2so == NULL", __func__);
1505 TAILQ_REMOVE(&s0->l2so->so_comp, l2so, so_list);
1506 s0->l2so->so_qlen --;
1507 l2so->so_head = NULL;
1510 error = soaccept(l2so, (struct sockaddr **) &l2sa);
1512 NG_BTSOCKET_RFCOMM_ERR(
1513 "%s: soaccept() on L2CAP socket failed, error=%d\n", __func__, error);
1514 soclose(l2so, FNONBLOCK);
1520 * Check if there is already active RFCOMM session between two devices.
1521 * If so then close L2CAP connection. We only support one RFCOMM session
1522 * between each pair of devices. Note that here we assume session in any
1523 * state. The session even could be in the middle of disconnecting.
1526 l2pcb = so2l2cap_pcb(l2so);
1527 s = ng_btsocket_rfcomm_session_by_addr(&l2pcb->src, &l2pcb->dst);
1529 /* Create a new RFCOMM session */
1530 error = ng_btsocket_rfcomm_session_create(&s, l2so, NULL, NULL,
1531 curthread /* XXX */);
1533 lockmgr(&s->session_lock, LK_EXCLUSIVE);
1536 s->state = NG_BTSOCKET_RFCOMM_SESSION_CONNECTED;
1539 * Adjust MTU on incomming connection. Reserve 5 bytes:
1540 * RFCOMM frame header, one extra byte for length and
1541 * one extra byte for credits.
1544 s->mtu = min(l2pcb->imtu, l2pcb->omtu) -
1545 sizeof(struct rfcomm_frame_hdr) - 1 - 1;
1547 lockmgr(&s->session_lock, LK_RELEASE);
1549 NG_BTSOCKET_RFCOMM_ALERT(
1550 "%s: Failed to create new RFCOMM session, error=%d\n", __func__, error);
1552 soclose(l2so, FNONBLOCK);
1555 NG_BTSOCKET_RFCOMM_WARN(
1556 "%s: Rejecting duplicating RFCOMM session between src=%x:%x:%x:%x:%x:%x and " \
1557 "dst=%x:%x:%x:%x:%x:%x, state=%d, flags=%#x\n", __func__,
1558 l2pcb->src.b[5], l2pcb->src.b[4], l2pcb->src.b[3],
1559 l2pcb->src.b[2], l2pcb->src.b[1], l2pcb->src.b[0],
1560 l2pcb->dst.b[5], l2pcb->dst.b[4], l2pcb->dst.b[3],
1561 l2pcb->dst.b[2], l2pcb->dst.b[1], l2pcb->dst.b[0],
1562 s->state, s->flags);
1565 soclose(l2so, FNONBLOCK);
1569 } /* ng_btsocket_rfcomm_session_accept */
1572 * Process connect() on RFCOMM session
1573 * XXX FIXME locking for "l2so"?
1577 ng_btsocket_rfcomm_session_connect(ng_btsocket_rfcomm_session_p s)
1579 ng_btsocket_l2cap_pcb_p l2pcb = so2l2cap_pcb(s->l2so);
1582 KKASSERT(lockowned(&s->session_lock) != 0);
1584 /* First check if connection has failed */
1585 if ((error = s->l2so->so_error) != 0) {
1586 s->l2so->so_error = 0;
1588 NG_BTSOCKET_RFCOMM_ERR(
1589 "%s: Could not connect RFCOMM session, error=%d, state=%d, flags=%#x\n",
1590 __func__, error, s->state, s->flags);
1595 /* Is connection still in progress? */
1596 if (s->l2so->so_state & SS_ISCONNECTING)
1600 * If we got here then we are connected. Send SABM on DLCI 0 to
1601 * open multiplexor channel.
1605 s->state = NG_BTSOCKET_RFCOMM_SESSION_CONNECTED;
1608 * Adjust MTU on outgoing connection. Reserve 5 bytes: RFCOMM
1609 * frame header, one extra byte for length and one extra byte
1613 s->mtu = min(l2pcb->imtu, l2pcb->omtu) -
1614 sizeof(struct rfcomm_frame_hdr) - 1 - 1;
1616 error = ng_btsocket_rfcomm_send_command(s,RFCOMM_FRAME_SABM,0);
1618 error = ng_btsocket_rfcomm_task_wakeup();
1622 }/* ng_btsocket_rfcomm_session_connect */
1625 * Receive data on RFCOMM session
1626 * XXX FIXME locking for "l2so"?
1630 ng_btsocket_rfcomm_session_receive(ng_btsocket_rfcomm_session_p s)
1633 int more, error, rcvflg, savelen = 0;
1635 KKASSERT(lockowned(&s->session_lock) != 0);
1637 /* Can we read from the L2CAP socket? */
1638 if (!soreadable(s->l2so))
1641 /* First check for error on L2CAP socket */
1642 if ((error = s->l2so->so_error) != 0) {
1643 s->l2so->so_error = 0;
1645 NG_BTSOCKET_RFCOMM_ERR(
1646 "%s: Could not receive data from L2CAP socket, error=%d, state=%d, flags=%#x\n",
1647 __func__, error, s->state, s->flags);
1653 * Read all packets from the L2CAP socket.
1654 * XXX FIXME/VERIFY is that correct? For now use m->m_nextpkt as
1655 * indication that there is more packets on the socket's buffer.
1656 * Also what should we use in uio.uio_resid?
1657 * May be s->mtu + sizeof(struct rfcomm_frame_hdr) + 1 + 1?
1661 for (more = 1; more; ) {
1662 /* Try to get next packet from socket */
1663 sbinit(&sio, savelen);
1664 rcvflg = MSG_WAITALL;
1665 error = soreceive(s->l2so, NULL, NULL, &sio, NULL, &rcvflg);
1667 if (error == EWOULDBLOCK)
1668 return (0); /* XXX can happen? */
1670 NG_BTSOCKET_RFCOMM_ERR(
1671 "%s: Could not receive data from L2CAP socket, error=%d\n", __func__, error);
1676 more = (sio.sb_mb->m_nextpkt != NULL);
1677 sio.sb_mb->m_nextpkt = NULL;
1679 ng_btsocket_rfcomm_receive_frame(s, sio.sb_mb);
1683 } /* ng_btsocket_rfcomm_session_receive */
1686 * Send data on RFCOMM session
1687 * XXX FIXME locking for "l2so"?
1691 ng_btsocket_rfcomm_session_send(ng_btsocket_rfcomm_session_p s)
1693 struct mbuf *m = NULL;
1695 struct netmsg_pru_send msg;
1697 KKASSERT(lockowned(&s->session_lock) != 0);
1699 /* Send as much as we can from the session queue */
1700 while (sowriteable(s->l2so)) {
1701 /* Check if socket still OK */
1702 if ((error = s->l2so->so_error) != 0) {
1703 s->l2so->so_error = 0;
1705 NG_BTSOCKET_RFCOMM_ERR(
1706 "%s: Detected error=%d on L2CAP socket, state=%d, flags=%#x\n",
1707 __func__, error, s->state, s->flags);
1712 NG_BT_MBUFQ_DEQUEUE(&s->outq, m);
1714 return (0); /* we are done */
1716 /* Call send function on the L2CAP socket */
1717 netmsg_init(&msg.base, s->l2so, &curthread->td_msgport,
1718 0, s->l2so->so_proto->pr_usrreqs->pru_send);
1722 msg.nm_control = NULL;
1723 msg.nm_td = curthread; /* XXX */
1724 error = lwkt_domsg(s->l2so->so_port, &msg.base.lmsg, 0);
1726 NG_BTSOCKET_RFCOMM_ERR(
1727 "%s: Could not send data to L2CAP socket, error=%d\n", __func__, error);
1734 } /* ng_btsocket_rfcomm_session_send */
1737 * Close and disconnect all DLCs for the given session. Caller must hold
1738 * s->sesson_mtx. Will wakeup session.
1742 ng_btsocket_rfcomm_session_clean(ng_btsocket_rfcomm_session_p s)
1744 ng_btsocket_rfcomm_pcb_p pcb = NULL, pcb_next = NULL;
1747 KKASSERT(lockowned(&s->session_lock) != 0);
1750 * Note: cannot use LIST_FOREACH because ng_btsocket_rfcomm_pcb_kill
1751 * will unlink DLC from the session
1754 for (pcb = LIST_FIRST(&s->dlcs); pcb != NULL; ) {
1755 lockmgr(&pcb->pcb_lock, LK_EXCLUSIVE);
1756 pcb_next = LIST_NEXT(pcb, session_next);
1758 NG_BTSOCKET_RFCOMM_INFO(
1759 "%s: Disconnecting dlci=%d, state=%d, flags=%#x\n",
1760 __func__, pcb->dlci, pcb->state, pcb->flags);
1762 if (pcb->state == NG_BTSOCKET_RFCOMM_DLC_CONNECTED)
1765 error = ECONNREFUSED;
1767 ng_btsocket_rfcomm_pcb_kill(pcb, error);
1769 lockmgr(&pcb->pcb_lock, LK_RELEASE);
1772 } /* ng_btsocket_rfcomm_session_clean */
1775 * Process all DLCs on the session. Caller MUST hold s->session_mtx.
1779 ng_btsocket_rfcomm_session_process_pcb(ng_btsocket_rfcomm_session_p s)
1781 ng_btsocket_rfcomm_pcb_p pcb = NULL, pcb_next = NULL;
1784 KKASSERT(lockowned(&s->session_lock) != 0);
1787 * Note: cannot use LIST_FOREACH because ng_btsocket_rfcomm_pcb_kill
1788 * will unlink DLC from the session
1791 for (pcb = LIST_FIRST(&s->dlcs); pcb != NULL; ) {
1792 lockmgr(&pcb->pcb_lock, LK_EXCLUSIVE);
1793 pcb_next = LIST_NEXT(pcb, session_next);
1795 switch (pcb->state) {
1798 * If DLC in W4_CONNECT state then we should check for both
1799 * timeout and detach.
1802 case NG_BTSOCKET_RFCOMM_DLC_W4_CONNECT:
1803 if (pcb->flags & NG_BTSOCKET_RFCOMM_DLC_DETACHED)
1804 ng_btsocket_rfcomm_pcb_kill(pcb, 0);
1805 else if (pcb->flags & NG_BTSOCKET_RFCOMM_DLC_TIMEDOUT)
1806 ng_btsocket_rfcomm_pcb_kill(pcb, ETIMEDOUT);
1810 * If DLC in CONFIGURING or CONNECTING state then we only
1811 * should check for timeout. If detach() was called then
1812 * DLC will be moved into DISCONNECTING state.
1815 case NG_BTSOCKET_RFCOMM_DLC_CONFIGURING:
1816 case NG_BTSOCKET_RFCOMM_DLC_CONNECTING:
1817 if (pcb->flags & NG_BTSOCKET_RFCOMM_DLC_TIMEDOUT)
1818 ng_btsocket_rfcomm_pcb_kill(pcb, ETIMEDOUT);
1822 * If DLC in CONNECTED state then we need to send data (if any)
1823 * from the socket's send queue. Note that we will send data
1824 * from either all sockets or none. This may overload session's
1825 * outgoing queue (but we do not check for that).
1827 * XXX FIXME need scheduler for RFCOMM sockets
1830 case NG_BTSOCKET_RFCOMM_DLC_CONNECTED:
1831 error = ng_btsocket_rfcomm_pcb_send(pcb, ALOT);
1833 ng_btsocket_rfcomm_pcb_kill(pcb, error);
1837 * If DLC in DISCONNECTING state then we must send DISC frame.
1838 * Note that if DLC has timeout set then we do not need to
1839 * resend DISC frame.
1841 * XXX FIXME need to drain all data from the socket's queue
1842 * if LINGER option was set
1845 case NG_BTSOCKET_RFCOMM_DLC_DISCONNECTING:
1846 if (!(pcb->flags & NG_BTSOCKET_RFCOMM_DLC_TIMO)) {
1847 error = ng_btsocket_rfcomm_send_command(
1848 pcb->session, RFCOMM_FRAME_DISC,
1851 ng_btsocket_rfcomm_timeout(pcb);
1853 ng_btsocket_rfcomm_pcb_kill(pcb, error);
1854 } else if (pcb->flags & NG_BTSOCKET_RFCOMM_DLC_TIMEDOUT)
1855 ng_btsocket_rfcomm_pcb_kill(pcb, ETIMEDOUT);
1858 /* case NG_BTSOCKET_RFCOMM_DLC_CLOSED: */
1860 panic("%s: Invalid DLC state=%d, flags=%#x",
1861 __func__, pcb->state, pcb->flags);
1865 lockmgr(&pcb->pcb_lock, LK_RELEASE);
1868 } /* ng_btsocket_rfcomm_session_process_pcb */
1871 * Find RFCOMM session between "src" and "dst".
1872 * Caller MUST hold ng_btsocket_rfcomm_sessions_mtx.
1875 static ng_btsocket_rfcomm_session_p
1876 ng_btsocket_rfcomm_session_by_addr(bdaddr_p src, bdaddr_p dst)
1878 ng_btsocket_rfcomm_session_p s = NULL;
1879 ng_btsocket_l2cap_pcb_p l2pcb = NULL;
1882 KKASSERT(lockowned(&ng_btsocket_rfcomm_sessions_lock) != 0);
1884 any_src = (bcmp(src, NG_HCI_BDADDR_ANY, sizeof(*src)) == 0);
1886 LIST_FOREACH(s, &ng_btsocket_rfcomm_sessions, next) {
1887 l2pcb = so2l2cap_pcb(s->l2so);
1889 if ((any_src || bcmp(&l2pcb->src, src, sizeof(*src)) == 0) &&
1890 bcmp(&l2pcb->dst, dst, sizeof(*dst)) == 0)
1895 } /* ng_btsocket_rfcomm_session_by_addr */
1897 /*****************************************************************************
1898 *****************************************************************************
1900 *****************************************************************************
1901 *****************************************************************************/
1904 * Process incoming RFCOMM frame. Caller must hold s->session_mtx.
1905 * XXX FIXME check frame length
1909 ng_btsocket_rfcomm_receive_frame(ng_btsocket_rfcomm_session_p s,
1912 struct rfcomm_frame_hdr *hdr = NULL;
1913 struct mbuf *m = NULL;
1915 u_int8_t dlci, type;
1918 KKASSERT(lockowned(&s->session_lock) != 0);
1920 /* Pullup as much as we can into first mbuf (for direct access) */
1921 length = min(m0->m_pkthdr.len, MHLEN);
1922 if (m0->m_len < length) {
1923 if ((m0 = m_pullup(m0, length)) == NULL) {
1924 NG_BTSOCKET_RFCOMM_ALERT(
1925 "%s: m_pullup(%d) failed\n", __func__, length);
1931 hdr = mtod(m0, struct rfcomm_frame_hdr *);
1932 dlci = RFCOMM_DLCI(hdr->address);
1933 type = RFCOMM_TYPE(hdr->control);
1935 /* Test EA bit in length. If not set then we have 2 bytes of length */
1936 if (!RFCOMM_EA(hdr->length)) {
1937 bcopy(&hdr->length, &length, sizeof(length));
1938 length = le16toh(length) >> 1;
1939 m_adj(m0, sizeof(*hdr) + 1);
1941 length = hdr->length >> 1;
1942 m_adj(m0, sizeof(*hdr));
1945 NG_BTSOCKET_RFCOMM_INFO(
1946 "%s: Got frame type=%#x, dlci=%d, length=%d, cr=%d, pf=%d, len=%d\n",
1947 __func__, type, dlci, length, RFCOMM_CR(hdr->address),
1948 RFCOMM_PF(hdr->control), m0->m_pkthdr.len);
1951 * Get FCS (the last byte in the frame)
1952 * XXX this will not work if mbuf chain ends with empty mbuf.
1953 * XXX let's hope it never happens :)
1956 for (m = m0; m->m_next != NULL; m = m->m_next)
1959 panic("%s: Empty mbuf at the end of the chain, len=%d",
1960 __func__, m->m_len);
1963 * Check FCS. We only need to calculate FCS on first 2 or 3 bytes
1964 * and already m_pullup'ed mbuf chain, so it should be safe.
1967 if (ng_btsocket_rfcomm_check_fcs((u_int8_t *) hdr, type, m->m_data[m->m_len - 1])) {
1968 NG_BTSOCKET_RFCOMM_ERR(
1969 "%s: Invalid RFCOMM packet. Bad checksum\n", __func__);
1975 m_adj(m0, -1); /* Trim FCS byte */
1978 * Process RFCOMM frame.
1980 * From TS 07.10 spec
1982 * "... In the case where a SABM or DISC command with the P bit set
1983 * to 0 is received then the received frame shall be discarded..."
1985 * "... If a unsolicited DM response is received then the frame shall
1986 * be processed irrespective of the P/F setting... "
1988 * "... The station may transmit response frames with the F bit set
1989 * to 0 at any opportunity on an asynchronous basis. However, in the
1990 * case where a UA response is received with the F bit set to 0 then
1991 * the received frame shall be discarded..."
1993 * From Bluetooth spec
1995 * "... When credit based flow control is being used, the meaning of
1996 * the P/F bit in the control field of the RFCOMM header is redefined
1997 * for UIH frames..."
2001 case RFCOMM_FRAME_SABM:
2002 if (RFCOMM_PF(hdr->control))
2003 error = ng_btsocket_rfcomm_receive_sabm(s, dlci);
2006 case RFCOMM_FRAME_DISC:
2007 if (RFCOMM_PF(hdr->control))
2008 error = ng_btsocket_rfcomm_receive_disc(s, dlci);
2011 case RFCOMM_FRAME_UA:
2012 if (RFCOMM_PF(hdr->control))
2013 error = ng_btsocket_rfcomm_receive_ua(s, dlci);
2016 case RFCOMM_FRAME_DM:
2017 error = ng_btsocket_rfcomm_receive_dm(s, dlci);
2020 case RFCOMM_FRAME_UIH:
2022 error = ng_btsocket_rfcomm_receive_mcc(s, m0);
2024 error = ng_btsocket_rfcomm_receive_uih(s, dlci,
2025 RFCOMM_PF(hdr->control), m0);
2031 NG_BTSOCKET_RFCOMM_ERR(
2032 "%s: Invalid RFCOMM packet. Unknown type=%#x\n", __func__, type);
2040 } /* ng_btsocket_rfcomm_receive_frame */
2043 * Process RFCOMM SABM frame
2047 ng_btsocket_rfcomm_receive_sabm(ng_btsocket_rfcomm_session_p s, int dlci)
2049 ng_btsocket_rfcomm_pcb_p pcb = NULL;
2052 KKASSERT(lockowned(&s->session_lock) != 0);
2054 NG_BTSOCKET_RFCOMM_INFO(
2055 "%s: Got SABM, session state=%d, flags=%#x, mtu=%d, dlci=%d\n",
2056 __func__, s->state, s->flags, s->mtu, dlci);
2058 /* DLCI == 0 means open multiplexor channel */
2061 case NG_BTSOCKET_RFCOMM_SESSION_CONNECTED:
2062 case NG_BTSOCKET_RFCOMM_SESSION_OPEN:
2063 error = ng_btsocket_rfcomm_send_command(s,
2064 RFCOMM_FRAME_UA, dlci);
2066 s->state = NG_BTSOCKET_RFCOMM_SESSION_OPEN;
2067 ng_btsocket_rfcomm_connect_cfm(s);
2069 s->state = NG_BTSOCKET_RFCOMM_SESSION_CLOSED;
2070 ng_btsocket_rfcomm_session_clean(s);
2075 NG_BTSOCKET_RFCOMM_WARN(
2076 "%s: Got SABM for session in invalid state state=%d, flags=%#x\n",
2077 __func__, s->state, s->flags);
2085 /* Make sure multiplexor channel is open */
2086 if (s->state != NG_BTSOCKET_RFCOMM_SESSION_OPEN) {
2087 NG_BTSOCKET_RFCOMM_ERR(
2088 "%s: Got SABM for dlci=%d with mulitplexor channel closed, state=%d, " \
2089 "flags=%#x\n", __func__, dlci, s->state, s->flags);
2095 * Check if we have this DLCI. This might happen when remote
2096 * peer uses PN command before actual open (SABM) happens.
2099 pcb = ng_btsocket_rfcomm_pcb_by_dlci(s, dlci);
2101 lockmgr(&pcb->pcb_lock, LK_EXCLUSIVE);
2103 if (pcb->state != NG_BTSOCKET_RFCOMM_DLC_CONNECTING) {
2104 NG_BTSOCKET_RFCOMM_ERR(
2105 "%s: Got SABM for dlci=%d in invalid state=%d, flags=%#x\n",
2106 __func__, dlci, pcb->state, pcb->flags);
2107 lockmgr(&pcb->pcb_lock, LK_RELEASE);
2112 ng_btsocket_rfcomm_untimeout(pcb);
2114 error = ng_btsocket_rfcomm_send_command(s,RFCOMM_FRAME_UA,dlci);
2116 error = ng_btsocket_rfcomm_send_msc(pcb);
2119 pcb->state = NG_BTSOCKET_RFCOMM_DLC_CONNECTED;
2120 soisconnected(pcb->so);
2122 ng_btsocket_rfcomm_pcb_kill(pcb, error);
2124 lockmgr(&pcb->pcb_lock, LK_RELEASE);
2130 * We do not have requested DLCI, so it must be an incoming connection
2131 * with default parameters. Try to accept it.
2134 pcb = ng_btsocket_rfcomm_connect_ind(s, RFCOMM_SRVCHANNEL(dlci));
2136 lockmgr(&pcb->pcb_lock, LK_EXCLUSIVE);
2140 error = ng_btsocket_rfcomm_send_command(s,RFCOMM_FRAME_UA,dlci);
2142 error = ng_btsocket_rfcomm_send_msc(pcb);
2145 pcb->state = NG_BTSOCKET_RFCOMM_DLC_CONNECTED;
2146 soisconnected(pcb->so);
2148 ng_btsocket_rfcomm_pcb_kill(pcb, error);
2150 lockmgr(&pcb->pcb_lock, LK_RELEASE);
2152 /* Nobody is listen()ing on the requested DLCI */
2153 error = ng_btsocket_rfcomm_send_command(s,RFCOMM_FRAME_DM,dlci);
2156 } /* ng_btsocket_rfcomm_receive_sabm */
2159 * Process RFCOMM DISC frame
2163 ng_btsocket_rfcomm_receive_disc(ng_btsocket_rfcomm_session_p s, int dlci)
2165 ng_btsocket_rfcomm_pcb_p pcb = NULL;
2168 KKASSERT(lockowned(&s->session_lock) != 0);
2170 NG_BTSOCKET_RFCOMM_INFO(
2171 "%s: Got DISC, session state=%d, flags=%#x, mtu=%d, dlci=%d\n",
2172 __func__, s->state, s->flags, s->mtu, dlci);
2174 /* DLCI == 0 means close multiplexor channel */
2176 /* XXX FIXME assume that remote side will close the socket */
2177 error = ng_btsocket_rfcomm_send_command(s, RFCOMM_FRAME_UA, 0);
2179 if (s->state == NG_BTSOCKET_RFCOMM_SESSION_DISCONNECTING)
2180 s->state = NG_BTSOCKET_RFCOMM_SESSION_CLOSED; /* XXX */
2182 s->state = NG_BTSOCKET_RFCOMM_SESSION_DISCONNECTING;
2184 s->state = NG_BTSOCKET_RFCOMM_SESSION_CLOSED; /* XXX */
2186 ng_btsocket_rfcomm_session_clean(s);
2188 pcb = ng_btsocket_rfcomm_pcb_by_dlci(s, dlci);
2192 lockmgr(&pcb->pcb_lock, LK_EXCLUSIVE);
2194 NG_BTSOCKET_RFCOMM_INFO(
2195 "%s: Got DISC for dlci=%d, state=%d, flags=%#x\n",
2196 __func__, dlci, pcb->state, pcb->flags);
2198 error = ng_btsocket_rfcomm_send_command(s,
2199 RFCOMM_FRAME_UA, dlci);
2201 if (pcb->state == NG_BTSOCKET_RFCOMM_DLC_CONNECTED)
2206 ng_btsocket_rfcomm_pcb_kill(pcb, err);
2208 lockmgr(&pcb->pcb_lock, LK_RELEASE);
2210 NG_BTSOCKET_RFCOMM_WARN(
2211 "%s: Got DISC for non-existing dlci=%d\n", __func__, dlci);
2213 error = ng_btsocket_rfcomm_send_command(s,
2214 RFCOMM_FRAME_DM, dlci);
2219 } /* ng_btsocket_rfcomm_receive_disc */
2222 * Process RFCOMM UA frame
2226 ng_btsocket_rfcomm_receive_ua(ng_btsocket_rfcomm_session_p s, int dlci)
2228 ng_btsocket_rfcomm_pcb_p pcb = NULL;
2231 KKASSERT(lockowned(&s->session_lock) != 0);
2233 NG_BTSOCKET_RFCOMM_INFO(
2234 "%s: Got UA, session state=%d, flags=%#x, mtu=%d, dlci=%d\n",
2235 __func__, s->state, s->flags, s->mtu, dlci);
2237 /* dlci == 0 means multiplexor channel */
2240 case NG_BTSOCKET_RFCOMM_SESSION_CONNECTED:
2241 s->state = NG_BTSOCKET_RFCOMM_SESSION_OPEN;
2242 ng_btsocket_rfcomm_connect_cfm(s);
2245 case NG_BTSOCKET_RFCOMM_SESSION_DISCONNECTING:
2246 s->state = NG_BTSOCKET_RFCOMM_SESSION_CLOSED;
2247 ng_btsocket_rfcomm_session_clean(s);
2251 NG_BTSOCKET_RFCOMM_WARN(
2252 "%s: Got UA for session in invalid state=%d(%d), flags=%#x, mtu=%d\n",
2253 __func__, s->state, INITIATOR(s), s->flags,
2262 /* Check if we have this DLCI */
2263 pcb = ng_btsocket_rfcomm_pcb_by_dlci(s, dlci);
2265 lockmgr(&pcb->pcb_lock, LK_EXCLUSIVE);
2267 NG_BTSOCKET_RFCOMM_INFO(
2268 "%s: Got UA for dlci=%d, state=%d, flags=%#x\n",
2269 __func__, dlci, pcb->state, pcb->flags);
2271 switch (pcb->state) {
2272 case NG_BTSOCKET_RFCOMM_DLC_CONNECTING:
2273 ng_btsocket_rfcomm_untimeout(pcb);
2275 error = ng_btsocket_rfcomm_send_msc(pcb);
2277 pcb->state = NG_BTSOCKET_RFCOMM_DLC_CONNECTED;
2278 soisconnected(pcb->so);
2282 case NG_BTSOCKET_RFCOMM_DLC_DISCONNECTING:
2283 ng_btsocket_rfcomm_pcb_kill(pcb, 0);
2287 NG_BTSOCKET_RFCOMM_WARN(
2288 "%s: Got UA for dlci=%d in invalid state=%d, flags=%#x\n",
2289 __func__, dlci, pcb->state, pcb->flags);
2294 lockmgr(&pcb->pcb_lock, LK_RELEASE);
2296 NG_BTSOCKET_RFCOMM_WARN(
2297 "%s: Got UA for non-existing dlci=%d\n", __func__, dlci);
2299 error = ng_btsocket_rfcomm_send_command(s,RFCOMM_FRAME_DM,dlci);
2303 } /* ng_btsocket_rfcomm_receive_ua */
2306 * Process RFCOMM DM frame
2310 ng_btsocket_rfcomm_receive_dm(ng_btsocket_rfcomm_session_p s, int dlci)
2312 ng_btsocket_rfcomm_pcb_p pcb = NULL;
2315 KKASSERT(lockowned(&s->session_lock) != 0);
2317 NG_BTSOCKET_RFCOMM_INFO(
2318 "%s: Got DM, session state=%d, flags=%#x, mtu=%d, dlci=%d\n",
2319 __func__, s->state, s->flags, s->mtu, dlci);
2321 /* DLCI == 0 means multiplexor channel */
2323 /* Disconnect all dlc's on the session */
2324 s->state = NG_BTSOCKET_RFCOMM_SESSION_CLOSED;
2325 ng_btsocket_rfcomm_session_clean(s);
2327 pcb = ng_btsocket_rfcomm_pcb_by_dlci(s, dlci);
2329 lockmgr(&pcb->pcb_lock, LK_EXCLUSIVE);
2331 NG_BTSOCKET_RFCOMM_INFO(
2332 "%s: Got DM for dlci=%d, state=%d, flags=%#x\n",
2333 __func__, dlci, pcb->state, pcb->flags);
2335 if (pcb->state == NG_BTSOCKET_RFCOMM_DLC_CONNECTED)
2338 error = ECONNREFUSED;
2340 ng_btsocket_rfcomm_pcb_kill(pcb, error);
2342 lockmgr(&pcb->pcb_lock, LK_RELEASE);
2344 NG_BTSOCKET_RFCOMM_WARN(
2345 "%s: Got DM for non-existing dlci=%d\n", __func__, dlci);
2349 } /* ng_btsocket_rfcomm_receive_dm */
2352 * Process RFCOMM UIH frame (data)
2356 ng_btsocket_rfcomm_receive_uih(ng_btsocket_rfcomm_session_p s, int dlci,
2357 int pf, struct mbuf *m0)
2359 ng_btsocket_rfcomm_pcb_p pcb = NULL;
2362 KKASSERT(lockowned(&s->session_lock) != 0);
2364 NG_BTSOCKET_RFCOMM_INFO(
2365 "%s: Got UIH, session state=%d, flags=%#x, mtu=%d, dlci=%d, pf=%d, len=%d\n",
2366 __func__, s->state, s->flags, s->mtu, dlci, pf,
2369 /* XXX should we do it here? Check for session flow control */
2370 if (s->flags & NG_BTSOCKET_RFCOMM_SESSION_LFC) {
2371 NG_BTSOCKET_RFCOMM_WARN(
2372 "%s: Got UIH with session flow control asserted, state=%d, flags=%#x\n",
2373 __func__, s->state, s->flags);
2377 /* Check if we have this dlci */
2378 pcb = ng_btsocket_rfcomm_pcb_by_dlci(s, dlci);
2380 NG_BTSOCKET_RFCOMM_WARN(
2381 "%s: Got UIH for non-existing dlci=%d\n", __func__, dlci);
2382 error = ng_btsocket_rfcomm_send_command(s,RFCOMM_FRAME_DM,dlci);
2386 lockmgr(&pcb->pcb_lock, LK_EXCLUSIVE);
2388 /* Check dlci state */
2389 if (pcb->state != NG_BTSOCKET_RFCOMM_DLC_CONNECTED) {
2390 NG_BTSOCKET_RFCOMM_WARN(
2391 "%s: Got UIH for dlci=%d in invalid state=%d, flags=%#x\n",
2392 __func__, dlci, pcb->state, pcb->flags);
2397 /* Check dlci flow control */
2398 if (((pcb->flags & NG_BTSOCKET_RFCOMM_DLC_CFC) && pcb->rx_cred <= 0) ||
2399 (pcb->lmodem & RFCOMM_MODEM_FC)) {
2400 NG_BTSOCKET_RFCOMM_ERR(
2401 "%s: Got UIH for dlci=%d with asserted flow control, state=%d, " \
2402 "flags=%#x, rx_cred=%d, lmodem=%#x\n",
2403 __func__, dlci, pcb->state, pcb->flags,
2404 pcb->rx_cred, pcb->lmodem);
2408 /* Did we get any credits? */
2409 if ((pcb->flags & NG_BTSOCKET_RFCOMM_DLC_CFC) && pf) {
2410 NG_BTSOCKET_RFCOMM_INFO(
2411 "%s: Got %d more credits for dlci=%d, state=%d, flags=%#x, " \
2412 "rx_cred=%d, tx_cred=%d\n",
2413 __func__, *mtod(m0, u_int8_t *), dlci, pcb->state,
2414 pcb->flags, pcb->rx_cred, pcb->tx_cred);
2416 pcb->tx_cred += *mtod(m0, u_int8_t *);
2419 /* Send more from the DLC. XXX check for errors? */
2420 ng_btsocket_rfcomm_pcb_send(pcb, ALOT);
2423 /* OK the of the rest of the mbuf is the data */
2424 if (m0->m_pkthdr.len > 0) {
2425 /* If we are using credit flow control decrease rx_cred here */
2426 if (pcb->flags & NG_BTSOCKET_RFCOMM_DLC_CFC) {
2427 /* Give remote peer more credits (if needed) */
2428 if (-- pcb->rx_cred <= RFCOMM_MAX_CREDITS / 2)
2429 ng_btsocket_rfcomm_send_credits(pcb);
2431 NG_BTSOCKET_RFCOMM_INFO(
2432 "%s: Remote side still has credits, dlci=%d, state=%d, flags=%#x, " \
2433 "rx_cred=%d, tx_cred=%d\n", __func__, dlci, pcb->state, pcb->flags,
2434 pcb->rx_cred, pcb->tx_cred);
2437 /* Check packet against mtu on dlci */
2438 if (m0->m_pkthdr.len > pcb->mtu) {
2439 NG_BTSOCKET_RFCOMM_ERR(
2440 "%s: Got oversized UIH for dlci=%d, state=%d, flags=%#x, mtu=%d, len=%d\n",
2441 __func__, dlci, pcb->state, pcb->flags,
2442 pcb->mtu, m0->m_pkthdr.len);
2445 } else if (m0->m_pkthdr.len > ssb_space(&pcb->so->so_rcv)) {
2448 * This is really bad. Receive queue on socket does
2449 * not have enough space for the packet. We do not
2450 * have any other choice but drop the packet.
2453 NG_BTSOCKET_RFCOMM_ERR(
2454 "%s: Not enough space in socket receive queue. Dropping UIH for dlci=%d, " \
2455 "state=%d, flags=%#x, len=%d, space=%ld\n",
2456 __func__, dlci, pcb->state, pcb->flags,
2457 m0->m_pkthdr.len, ssb_space(&pcb->so->so_rcv));
2461 /* Append packet to the socket receive queue */
2462 sbappend(&pcb->so->so_rcv.sb, m0);
2469 lockmgr(&pcb->pcb_lock, LK_RELEASE);
2471 NG_FREE_M(m0); /* checks for != NULL */
2474 } /* ng_btsocket_rfcomm_receive_uih */
2477 * Process RFCOMM MCC command (Multiplexor)
2479 * From TS 07.10 spec
2481 * "5.4.3.1 Information Data
2483 * ...The frames (UIH) sent by the initiating station have the C/R bit set
2484 * to 1 and those sent by the responding station have the C/R bit set to 0..."
2486 * "5.4.6.2 Operating procedures
2488 * Messages always exist in pairs; a command message and a corresponding
2489 * response message. If the C/R bit is set to 1 the message is a command,
2490 * if it is set to 0 the message is a response...
2494 * NOTE: Notice that when UIH frames are used to convey information on DLCI 0
2495 * there are at least two different fields that contain a C/R bit, and the
2496 * bits are set of different form. The C/R bit in the Type field shall be set
2497 * as it is stated above, while the C/R bit in the Address field (see subclause
2498 * 5.2.1.2) shall be set as it is described in subclause 5.4.3.1."
2502 ng_btsocket_rfcomm_receive_mcc(ng_btsocket_rfcomm_session_p s, struct mbuf *m0)
2504 struct rfcomm_mcc_hdr *hdr = NULL;
2505 u_int8_t cr, type, length;
2507 KKASSERT(lockowned(&s->session_lock) != 0);
2510 * We can access data directly in the first mbuf, because we have
2511 * m_pullup()'ed mbuf chain in ng_btsocket_rfcomm_receive_frame().
2512 * All MCC commands should fit into single mbuf (except probably TEST).
2515 hdr = mtod(m0, struct rfcomm_mcc_hdr *);
2516 cr = RFCOMM_CR(hdr->type);
2517 type = RFCOMM_MCC_TYPE(hdr->type);
2518 length = RFCOMM_MCC_LENGTH(hdr->length);
2520 /* Check MCC frame length */
2521 if (sizeof(*hdr) + length != m0->m_pkthdr.len) {
2522 NG_BTSOCKET_RFCOMM_ERR(
2523 "%s: Invalid MCC frame length=%d, len=%d\n",
2524 __func__, length, m0->m_pkthdr.len);
2531 case RFCOMM_MCC_TEST:
2532 return (ng_btsocket_rfcomm_receive_test(s, m0));
2535 case RFCOMM_MCC_FCON:
2536 case RFCOMM_MCC_FCOFF:
2537 return (ng_btsocket_rfcomm_receive_fc(s, m0));
2540 case RFCOMM_MCC_MSC:
2541 return (ng_btsocket_rfcomm_receive_msc(s, m0));
2544 case RFCOMM_MCC_RPN:
2545 return (ng_btsocket_rfcomm_receive_rpn(s, m0));
2548 case RFCOMM_MCC_RLS:
2549 return (ng_btsocket_rfcomm_receive_rls(s, m0));
2553 return (ng_btsocket_rfcomm_receive_pn(s, m0));
2556 case RFCOMM_MCC_NSC:
2557 NG_BTSOCKET_RFCOMM_ERR(
2558 "%s: Got MCC NSC, type=%#x, cr=%d, length=%d, session state=%d, flags=%#x, " \
2559 "mtu=%d, len=%d\n", __func__, RFCOMM_MCC_TYPE(*((u_int8_t *)(hdr + 1))), cr,
2560 length, s->state, s->flags, s->mtu, m0->m_pkthdr.len);
2565 NG_BTSOCKET_RFCOMM_ERR(
2566 "%s: Got unknown MCC, type=%#x, cr=%d, length=%d, session state=%d, " \
2567 "flags=%#x, mtu=%d, len=%d\n",
2568 __func__, type, cr, length, s->state, s->flags,
2569 s->mtu, m0->m_pkthdr.len);
2571 /* Reuse mbuf to send NSC */
2572 hdr = mtod(m0, struct rfcomm_mcc_hdr *);
2573 m0->m_pkthdr.len = m0->m_len = sizeof(*hdr);
2575 /* Create MCC NSC header */
2576 hdr->type = RFCOMM_MKMCC_TYPE(0, RFCOMM_MCC_NSC);
2577 hdr->length = RFCOMM_MKLEN8(1);
2579 /* Put back MCC command type we did not like */
2580 m0->m_data[m0->m_len] = RFCOMM_MKMCC_TYPE(cr, type);
2581 m0->m_pkthdr.len ++;
2584 /* Send UIH frame */
2585 return (ng_btsocket_rfcomm_send_uih(s,
2586 RFCOMM_MKADDRESS(INITIATOR(s), 0), 0, 0, m0));
2591 } /* ng_btsocket_rfcomm_receive_mcc */
2594 * Receive RFCOMM TEST MCC command
2598 ng_btsocket_rfcomm_receive_test(ng_btsocket_rfcomm_session_p s, struct mbuf *m0)
2600 struct rfcomm_mcc_hdr *hdr = mtod(m0, struct rfcomm_mcc_hdr *);
2603 KKASSERT(lockowned(&s->session_lock) != 0);
2605 NG_BTSOCKET_RFCOMM_INFO(
2606 "%s: Got MCC TEST, cr=%d, length=%d, session state=%d, flags=%#x, mtu=%d, " \
2607 "len=%d\n", __func__, RFCOMM_CR(hdr->type), RFCOMM_MCC_LENGTH(hdr->length),
2608 s->state, s->flags, s->mtu, m0->m_pkthdr.len);
2610 if (RFCOMM_CR(hdr->type)) {
2611 hdr->type = RFCOMM_MKMCC_TYPE(0, RFCOMM_MCC_TEST);
2612 error = ng_btsocket_rfcomm_send_uih(s,
2613 RFCOMM_MKADDRESS(INITIATOR(s), 0), 0, 0, m0);
2615 NG_FREE_M(m0); /* XXX ignore response */
2618 } /* ng_btsocket_rfcomm_receive_test */
2621 * Receive RFCOMM FCON/FCOFF MCC command
2625 ng_btsocket_rfcomm_receive_fc(ng_btsocket_rfcomm_session_p s, struct mbuf *m0)
2627 struct rfcomm_mcc_hdr *hdr = mtod(m0, struct rfcomm_mcc_hdr *);
2628 u_int8_t type = RFCOMM_MCC_TYPE(hdr->type);
2631 KKASSERT(lockowned(&s->session_lock) != 0);
2634 * Turn ON/OFF aggregate flow on the entire session. When remote peer
2635 * asserted flow control no transmission shall occur except on dlci 0
2636 * (control channel).
2639 NG_BTSOCKET_RFCOMM_INFO(
2640 "%s: Got MCC FC%s, cr=%d, length=%d, session state=%d, flags=%#x, mtu=%d, " \
2641 "len=%d\n", __func__, (type == RFCOMM_MCC_FCON)? "ON" : "OFF",
2642 RFCOMM_CR(hdr->type), RFCOMM_MCC_LENGTH(hdr->length),
2643 s->state, s->flags, s->mtu, m0->m_pkthdr.len);
2645 if (RFCOMM_CR(hdr->type)) {
2646 if (type == RFCOMM_MCC_FCON)
2647 s->flags &= ~NG_BTSOCKET_RFCOMM_SESSION_RFC;
2649 s->flags |= NG_BTSOCKET_RFCOMM_SESSION_RFC;
2651 hdr->type = RFCOMM_MKMCC_TYPE(0, type);
2652 error = ng_btsocket_rfcomm_send_uih(s,
2653 RFCOMM_MKADDRESS(INITIATOR(s), 0), 0, 0, m0);
2655 NG_FREE_M(m0); /* XXX ignore response */
2658 } /* ng_btsocket_rfcomm_receive_fc */
2661 * Receive RFCOMM MSC MCC command
2665 ng_btsocket_rfcomm_receive_msc(ng_btsocket_rfcomm_session_p s, struct mbuf *m0)
2667 struct rfcomm_mcc_hdr *hdr = mtod(m0, struct rfcomm_mcc_hdr*);
2668 struct rfcomm_mcc_msc *msc = (struct rfcomm_mcc_msc *)(hdr+1);
2669 ng_btsocket_rfcomm_pcb_t *pcb = NULL;
2672 KKASSERT(lockowned(&s->session_lock) != 0);
2674 NG_BTSOCKET_RFCOMM_INFO(
2675 "%s: Got MCC MSC, dlci=%d, cr=%d, length=%d, session state=%d, flags=%#x, " \
2677 __func__, RFCOMM_DLCI(msc->address), RFCOMM_CR(hdr->type),
2678 RFCOMM_MCC_LENGTH(hdr->length), s->state, s->flags,
2679 s->mtu, m0->m_pkthdr.len);
2681 if (RFCOMM_CR(hdr->type)) {
2682 pcb = ng_btsocket_rfcomm_pcb_by_dlci(s, RFCOMM_DLCI(msc->address));
2684 NG_BTSOCKET_RFCOMM_WARN(
2685 "%s: Got MSC command for non-existing dlci=%d\n",
2686 __func__, RFCOMM_DLCI(msc->address));
2692 lockmgr(&pcb->pcb_lock, LK_EXCLUSIVE);
2694 if (pcb->state != NG_BTSOCKET_RFCOMM_DLC_CONNECTING &&
2695 pcb->state != NG_BTSOCKET_RFCOMM_DLC_CONNECTED) {
2696 NG_BTSOCKET_RFCOMM_WARN(
2697 "%s: Got MSC on dlci=%d in invalid state=%d\n",
2698 __func__, RFCOMM_DLCI(msc->address),
2701 lockmgr(&pcb->pcb_lock, LK_RELEASE);
2707 pcb->rmodem = msc->modem; /* Update remote port signals */
2709 hdr->type = RFCOMM_MKMCC_TYPE(0, RFCOMM_MCC_MSC);
2710 error = ng_btsocket_rfcomm_send_uih(s,
2711 RFCOMM_MKADDRESS(INITIATOR(s), 0), 0, 0, m0);
2714 /* Send more data from DLC. XXX check for errors? */
2715 if (!(pcb->rmodem & RFCOMM_MODEM_FC) &&
2716 !(pcb->flags & NG_BTSOCKET_RFCOMM_DLC_CFC))
2717 ng_btsocket_rfcomm_pcb_send(pcb, ALOT);
2720 lockmgr(&pcb->pcb_lock, LK_RELEASE);
2722 NG_FREE_M(m0); /* XXX ignore response */
2725 } /* ng_btsocket_rfcomm_receive_msc */
2728 * Receive RFCOMM RPN MCC command
2729 * XXX FIXME do we need htole16/le16toh for RPN param_mask?
2733 ng_btsocket_rfcomm_receive_rpn(ng_btsocket_rfcomm_session_p s, struct mbuf *m0)
2735 struct rfcomm_mcc_hdr *hdr = mtod(m0, struct rfcomm_mcc_hdr *);
2736 struct rfcomm_mcc_rpn *rpn = (struct rfcomm_mcc_rpn *)(hdr + 1);
2738 u_int16_t param_mask;
2739 u_int8_t bit_rate, data_bits, stop_bits, parity,
2740 flow_control, xon_char, xoff_char;
2742 KKASSERT(lockowned(&s->session_lock) != 0);
2744 NG_BTSOCKET_RFCOMM_INFO(
2745 "%s: Got MCC RPN, dlci=%d, cr=%d, length=%d, session state=%d, flags=%#x, " \
2747 __func__, RFCOMM_DLCI(rpn->dlci), RFCOMM_CR(hdr->type),
2748 RFCOMM_MCC_LENGTH(hdr->length), s->state, s->flags,
2749 s->mtu, m0->m_pkthdr.len);
2751 if (RFCOMM_CR(hdr->type)) {
2752 param_mask = RFCOMM_RPN_PM_ALL;
2754 if (RFCOMM_MCC_LENGTH(hdr->length) == 1) {
2755 /* Request - return default setting */
2756 bit_rate = RFCOMM_RPN_BR_115200;
2757 data_bits = RFCOMM_RPN_DATA_8;
2758 stop_bits = RFCOMM_RPN_STOP_1;
2759 parity = RFCOMM_RPN_PARITY_NONE;
2760 flow_control = RFCOMM_RPN_FLOW_NONE;
2761 xon_char = RFCOMM_RPN_XON_CHAR;
2762 xoff_char = RFCOMM_RPN_XOFF_CHAR;
2765 * Ignore/accept bit_rate, 8 bits, 1 stop bit, no
2766 * parity, no flow control lines, default XON/XOFF
2770 bit_rate = rpn->bit_rate;
2771 rpn->param_mask = le16toh(rpn->param_mask); /* XXX */
2773 data_bits = RFCOMM_RPN_DATA_BITS(rpn->line_settings);
2774 if (rpn->param_mask & RFCOMM_RPN_PM_DATA &&
2775 data_bits != RFCOMM_RPN_DATA_8) {
2776 data_bits = RFCOMM_RPN_DATA_8;
2777 param_mask ^= RFCOMM_RPN_PM_DATA;
2780 stop_bits = RFCOMM_RPN_STOP_BITS(rpn->line_settings);
2781 if (rpn->param_mask & RFCOMM_RPN_PM_STOP &&
2782 stop_bits != RFCOMM_RPN_STOP_1) {
2783 stop_bits = RFCOMM_RPN_STOP_1;
2784 param_mask ^= RFCOMM_RPN_PM_STOP;
2787 parity = RFCOMM_RPN_PARITY(rpn->line_settings);
2788 if (rpn->param_mask & RFCOMM_RPN_PM_PARITY &&
2789 parity != RFCOMM_RPN_PARITY_NONE) {
2790 parity = RFCOMM_RPN_PARITY_NONE;
2791 param_mask ^= RFCOMM_RPN_PM_PARITY;
2794 flow_control = rpn->flow_control;
2795 if (rpn->param_mask & RFCOMM_RPN_PM_FLOW &&
2796 flow_control != RFCOMM_RPN_FLOW_NONE) {
2797 flow_control = RFCOMM_RPN_FLOW_NONE;
2798 param_mask ^= RFCOMM_RPN_PM_FLOW;
2801 xon_char = rpn->xon_char;
2802 if (rpn->param_mask & RFCOMM_RPN_PM_XON &&
2803 xon_char != RFCOMM_RPN_XON_CHAR) {
2804 xon_char = RFCOMM_RPN_XON_CHAR;
2805 param_mask ^= RFCOMM_RPN_PM_XON;
2808 xoff_char = rpn->xoff_char;
2809 if (rpn->param_mask & RFCOMM_RPN_PM_XOFF &&
2810 xoff_char != RFCOMM_RPN_XOFF_CHAR) {
2811 xoff_char = RFCOMM_RPN_XOFF_CHAR;
2812 param_mask ^= RFCOMM_RPN_PM_XOFF;
2816 rpn->bit_rate = bit_rate;
2817 rpn->line_settings = RFCOMM_MKRPN_LINE_SETTINGS(data_bits,
2819 rpn->flow_control = flow_control;
2820 rpn->xon_char = xon_char;
2821 rpn->xoff_char = xoff_char;
2822 rpn->param_mask = htole16(param_mask); /* XXX */
2824 m0->m_pkthdr.len = m0->m_len = sizeof(*hdr) + sizeof(*rpn);
2826 hdr->type = RFCOMM_MKMCC_TYPE(0, RFCOMM_MCC_RPN);
2827 error = ng_btsocket_rfcomm_send_uih(s,
2828 RFCOMM_MKADDRESS(INITIATOR(s), 0), 0, 0, m0);
2830 NG_FREE_M(m0); /* XXX ignore response */
2833 } /* ng_btsocket_rfcomm_receive_rpn */
2836 * Receive RFCOMM RLS MCC command
2840 ng_btsocket_rfcomm_receive_rls(ng_btsocket_rfcomm_session_p s, struct mbuf *m0)
2842 struct rfcomm_mcc_hdr *hdr = mtod(m0, struct rfcomm_mcc_hdr *);
2843 struct rfcomm_mcc_rls *rls = (struct rfcomm_mcc_rls *)(hdr + 1);
2846 KKASSERT(lockowned(&s->session_lock) != 0);
2849 * XXX FIXME Do we have to do anything else here? Remote peer tries to
2850 * tell us something about DLCI. Just report what we have received and
2851 * return back received values as required by TS 07.10 spec.
2854 NG_BTSOCKET_RFCOMM_INFO(
2855 "%s: Got MCC RLS, dlci=%d, status=%#x, cr=%d, length=%d, session state=%d, " \
2856 "flags=%#x, mtu=%d, len=%d\n",
2857 __func__, RFCOMM_DLCI(rls->address), rls->status,
2858 RFCOMM_CR(hdr->type), RFCOMM_MCC_LENGTH(hdr->length),
2859 s->state, s->flags, s->mtu, m0->m_pkthdr.len);
2861 if (RFCOMM_CR(hdr->type)) {
2862 if (rls->status & 0x1)
2863 NG_BTSOCKET_RFCOMM_ERR(
2864 "%s: Got RLS dlci=%d, error=%#x\n", __func__, RFCOMM_DLCI(rls->address),
2867 hdr->type = RFCOMM_MKMCC_TYPE(0, RFCOMM_MCC_RLS);
2868 error = ng_btsocket_rfcomm_send_uih(s,
2869 RFCOMM_MKADDRESS(INITIATOR(s), 0), 0, 0, m0);
2871 NG_FREE_M(m0); /* XXX ignore responses */
2874 } /* ng_btsocket_rfcomm_receive_rls */
2877 * Receive RFCOMM PN MCC command
2881 ng_btsocket_rfcomm_receive_pn(ng_btsocket_rfcomm_session_p s, struct mbuf *m0)
2883 struct rfcomm_mcc_hdr *hdr = mtod(m0, struct rfcomm_mcc_hdr*);
2884 struct rfcomm_mcc_pn *pn = (struct rfcomm_mcc_pn *)(hdr+1);
2885 ng_btsocket_rfcomm_pcb_t *pcb = NULL;
2888 KKASSERT(lockowned(&s->session_lock) != 0);
2890 NG_BTSOCKET_RFCOMM_INFO(
2891 "%s: Got MCC PN, dlci=%d, cr=%d, length=%d, flow_control=%#x, priority=%d, " \
2892 "ack_timer=%d, mtu=%d, max_retrans=%d, credits=%d, session state=%d, " \
2893 "flags=%#x, session mtu=%d, len=%d\n",
2894 __func__, pn->dlci, RFCOMM_CR(hdr->type),
2895 RFCOMM_MCC_LENGTH(hdr->length), pn->flow_control, pn->priority,
2896 pn->ack_timer, le16toh(pn->mtu), pn->max_retrans, pn->credits,
2897 s->state, s->flags, s->mtu, m0->m_pkthdr.len);
2899 if (pn->dlci == 0) {
2900 NG_BTSOCKET_RFCOMM_ERR("%s: Zero dlci in MCC PN\n", __func__);
2906 /* Check if we have this dlci */
2907 pcb = ng_btsocket_rfcomm_pcb_by_dlci(s, pn->dlci);
2909 lockmgr(&pcb->pcb_lock, LK_EXCLUSIVE);
2911 if (RFCOMM_CR(hdr->type)) {
2913 ng_btsocket_rfcomm_set_pn(pcb, 1, pn->flow_control,
2914 pn->credits, pn->mtu);
2916 if (pcb->flags & NG_BTSOCKET_RFCOMM_DLC_CFC) {
2917 pn->flow_control = 0xe0;
2918 pn->credits = RFCOMM_DEFAULT_CREDITS;
2920 pn->flow_control = 0;
2924 hdr->type = RFCOMM_MKMCC_TYPE(0, RFCOMM_MCC_PN);
2925 error = ng_btsocket_rfcomm_send_uih(s,
2926 RFCOMM_MKADDRESS(INITIATOR(s), 0),
2929 /* PN Response - proceed with SABM. Timeout still set */
2930 if (pcb->state == NG_BTSOCKET_RFCOMM_DLC_CONFIGURING) {
2931 ng_btsocket_rfcomm_set_pn(pcb, 0,
2932 pn->flow_control, pn->credits, pn->mtu);
2934 pcb->state = NG_BTSOCKET_RFCOMM_DLC_CONNECTING;
2935 error = ng_btsocket_rfcomm_send_command(s,
2936 RFCOMM_FRAME_SABM, pn->dlci);
2938 NG_BTSOCKET_RFCOMM_WARN(
2939 "%s: Got PN response for dlci=%d in invalid state=%d\n",
2940 __func__, pn->dlci, pcb->state);
2945 lockmgr(&pcb->pcb_lock, LK_RELEASE);
2946 } else if (RFCOMM_CR(hdr->type)) {
2947 /* PN request to non-existing dlci - incomming connection */
2948 pcb = ng_btsocket_rfcomm_connect_ind(s,
2949 RFCOMM_SRVCHANNEL(pn->dlci));
2951 lockmgr(&pcb->pcb_lock, LK_EXCLUSIVE);
2953 pcb->dlci = pn->dlci;
2955 ng_btsocket_rfcomm_set_pn(pcb, 1, pn->flow_control,
2956 pn->credits, pn->mtu);
2958 if (pcb->flags & NG_BTSOCKET_RFCOMM_DLC_CFC) {
2959 pn->flow_control = 0xe0;
2960 pn->credits = RFCOMM_DEFAULT_CREDITS;
2962 pn->flow_control = 0;
2966 hdr->type = RFCOMM_MKMCC_TYPE(0, RFCOMM_MCC_PN);
2967 error = ng_btsocket_rfcomm_send_uih(s,
2968 RFCOMM_MKADDRESS(INITIATOR(s), 0),
2972 ng_btsocket_rfcomm_timeout(pcb);
2973 pcb->state = NG_BTSOCKET_RFCOMM_DLC_CONNECTING;
2974 soisconnecting(pcb->so);
2976 ng_btsocket_rfcomm_pcb_kill(pcb, error);
2978 lockmgr(&pcb->pcb_lock, LK_RELEASE);
2980 /* Nobody is listen()ing on this channel */
2981 error = ng_btsocket_rfcomm_send_command(s,
2982 RFCOMM_FRAME_DM, pn->dlci);
2986 NG_FREE_M(m0); /* XXX ignore response to non-existing dlci */
2989 } /* ng_btsocket_rfcomm_receive_pn */
2992 * Set PN parameters for dlci. Caller must hold pcb->pcb_mtx.
2994 * From Bluetooth spec.
2996 * "... The CL1 - CL4 field is completely redefined. (In TS07.10 this defines
2997 * the convergence layer to use, which is not applicable to RFCOMM. In RFCOMM,
2998 * in Bluetooth versions up to 1.0B, this field was forced to 0).
3000 * In the PN request sent prior to a DLC establishment, this field must contain
3001 * the value 15 (0xF), indicating support of credit based flow control in the
3002 * sender. See Table 5.3 below. If the PN response contains any other value
3003 * than 14 (0xE) in this field, it is inferred that the peer RFCOMM entity is
3004 * not supporting the credit based flow control feature. (This is only possible
3005 * if the peer RFCOMM implementation is only conforming to Bluetooth version
3006 * 1.0B.) If a PN request is sent on an already open DLC, then this field must
3007 * contain the value zero; it is not possible to set initial credits more
3008 * than once per DLC activation. A responding implementation must set this
3009 * field in the PN response to 14 (0xE), if (and only if) the value in the PN
3010 * request was 15..."
3014 ng_btsocket_rfcomm_set_pn(ng_btsocket_rfcomm_pcb_p pcb, u_int8_t cr,
3015 u_int8_t flow_control, u_int8_t credits, u_int16_t mtu)
3017 KKASSERT(lockowned(&pcb->pcb_lock) != 0);
3019 pcb->mtu = le16toh(mtu);
3022 if (flow_control == 0xf0) {
3023 pcb->flags |= NG_BTSOCKET_RFCOMM_DLC_CFC;
3024 pcb->tx_cred = credits;
3026 pcb->flags &= ~NG_BTSOCKET_RFCOMM_DLC_CFC;
3030 if (flow_control == 0xe0) {
3031 pcb->flags |= NG_BTSOCKET_RFCOMM_DLC_CFC;
3032 pcb->tx_cred = credits;
3034 pcb->flags &= ~NG_BTSOCKET_RFCOMM_DLC_CFC;
3039 NG_BTSOCKET_RFCOMM_INFO(
3040 "%s: cr=%d, dlci=%d, state=%d, flags=%#x, mtu=%d, rx_cred=%d, tx_cred=%d\n",
3041 __func__, cr, pcb->dlci, pcb->state, pcb->flags, pcb->mtu,
3042 pcb->rx_cred, pcb->tx_cred);
3043 } /* ng_btsocket_rfcomm_set_pn */
3046 * Send RFCOMM SABM/DISC/UA/DM frames. Caller must hold s->session_mtx
3050 ng_btsocket_rfcomm_send_command(ng_btsocket_rfcomm_session_p s,
3051 u_int8_t type, u_int8_t dlci)
3053 struct rfcomm_cmd_hdr *hdr = NULL;
3054 struct mbuf *m = NULL;
3057 KKASSERT(lockowned(&s->session_lock) != 0);
3059 NG_BTSOCKET_RFCOMM_INFO(
3060 "%s: Sending command type %#x, session state=%d, flags=%#x, mtu=%d, dlci=%d\n",
3061 __func__, type, s->state, s->flags, s->mtu, dlci);
3064 case RFCOMM_FRAME_SABM:
3065 case RFCOMM_FRAME_DISC:
3069 case RFCOMM_FRAME_UA:
3070 case RFCOMM_FRAME_DM:
3075 panic("%s: Invalid frame type=%#x", __func__, type);
3080 MGETHDR(m, M_NOWAIT, MT_DATA);
3084 m->m_pkthdr.len = m->m_len = sizeof(*hdr);
3086 hdr = mtod(m, struct rfcomm_cmd_hdr *);
3087 hdr->address = RFCOMM_MKADDRESS(cr, dlci);
3088 hdr->control = RFCOMM_MKCONTROL(type, 1);
3089 hdr->length = RFCOMM_MKLEN8(0);
3090 hdr->fcs = ng_btsocket_rfcomm_fcs3((u_int8_t *) hdr);
3092 NG_BT_MBUFQ_ENQUEUE(&s->outq, m);
3095 } /* ng_btsocket_rfcomm_send_command */
3098 * Send RFCOMM UIH frame. Caller must hold s->session_mtx
3102 ng_btsocket_rfcomm_send_uih(ng_btsocket_rfcomm_session_p s, u_int8_t address,
3103 u_int8_t pf, u_int8_t credits, struct mbuf *data)
3105 struct rfcomm_frame_hdr *hdr = NULL;
3106 struct mbuf *m = NULL, *mcrc = NULL;
3109 KKASSERT(lockowned(&s->session_lock) != 0);
3111 MGETHDR(m, M_NOWAIT, MT_DATA);
3116 m->m_pkthdr.len = m->m_len = sizeof(*hdr);
3118 MGET(mcrc, M_NOWAIT, MT_DATA);
3125 /* Fill UIH frame header */
3126 hdr = mtod(m, struct rfcomm_frame_hdr *);
3127 hdr->address = address;
3128 hdr->control = RFCOMM_MKCONTROL(RFCOMM_FRAME_UIH, pf);
3131 mcrc->m_data[0] = ng_btsocket_rfcomm_fcs2((u_int8_t *) hdr);
3133 /* Put length back */
3134 length = (data != NULL)? data->m_pkthdr.len : 0;
3136 u_int16_t l = htole16(RFCOMM_MKLEN16(length));
3138 bcopy(&l, &hdr->length, sizeof(l));
3142 hdr->length = RFCOMM_MKLEN8(length);
3145 m->m_data[m->m_len] = credits;
3153 m->m_pkthdr.len += length;
3160 NG_BTSOCKET_RFCOMM_INFO(
3161 "%s: Sending UIH state=%d, flags=%#x, address=%d, length=%d, pf=%d, " \
3162 "credits=%d, len=%d\n",
3163 __func__, s->state, s->flags, address, length, pf, credits,
3166 NG_BT_MBUFQ_ENQUEUE(&s->outq, m);
3169 } /* ng_btsocket_rfcomm_send_uih */
3172 * Send MSC request. Caller must hold pcb->pcb_mtx and pcb->session->session_mtx
3176 ng_btsocket_rfcomm_send_msc(ng_btsocket_rfcomm_pcb_p pcb)
3178 struct mbuf *m = NULL;
3179 struct rfcomm_mcc_hdr *hdr = NULL;
3180 struct rfcomm_mcc_msc *msc = NULL;
3182 KKASSERT(lockowned(&pcb->session->session_lock) != 0);
3183 KKASSERT(lockowned(&pcb->pcb_lock) != 0);
3185 MGETHDR(m, M_NOWAIT, MT_DATA);
3189 m->m_pkthdr.len = m->m_len = sizeof(*hdr) + sizeof(*msc);
3191 hdr = mtod(m, struct rfcomm_mcc_hdr *);
3192 msc = (struct rfcomm_mcc_msc *)(hdr + 1);
3194 hdr->type = RFCOMM_MKMCC_TYPE(1, RFCOMM_MCC_MSC);
3195 hdr->length = RFCOMM_MKLEN8(sizeof(*msc));
3197 msc->address = RFCOMM_MKADDRESS(1, pcb->dlci);
3198 msc->modem = pcb->lmodem;
3200 NG_BTSOCKET_RFCOMM_INFO(
3201 "%s: Sending MSC dlci=%d, state=%d, flags=%#x, address=%d, modem=%#x\n",
3202 __func__, pcb->dlci, pcb->state, pcb->flags, msc->address,
3205 return (ng_btsocket_rfcomm_send_uih(pcb->session,
3206 RFCOMM_MKADDRESS(INITIATOR(pcb->session), 0), 0, 0, m));
3207 } /* ng_btsocket_rfcomm_send_msc */
3210 * Send PN request. Caller must hold pcb->pcb_mtx and pcb->session->session_mtx
3214 ng_btsocket_rfcomm_send_pn(ng_btsocket_rfcomm_pcb_p pcb)
3216 struct mbuf *m = NULL;
3217 struct rfcomm_mcc_hdr *hdr = NULL;
3218 struct rfcomm_mcc_pn *pn = NULL;
3220 KKASSERT(lockowned(&pcb->session->session_lock) != 0);
3221 KKASSERT(lockowned(&pcb->pcb_lock) != 0);
3223 MGETHDR(m, M_NOWAIT, MT_DATA);
3227 m->m_pkthdr.len = m->m_len = sizeof(*hdr) + sizeof(*pn);
3229 hdr = mtod(m, struct rfcomm_mcc_hdr *);
3230 pn = (struct rfcomm_mcc_pn *)(hdr + 1);
3232 hdr->type = RFCOMM_MKMCC_TYPE(1, RFCOMM_MCC_PN);
3233 hdr->length = RFCOMM_MKLEN8(sizeof(*pn));
3235 pn->dlci = pcb->dlci;
3238 * Set default DLCI priority as described in GSM 07.10
3239 * (ETSI TS 101 369) clause 5.6 page 42
3242 pn->priority = (pcb->dlci < 56)? (((pcb->dlci >> 3) << 3) + 7) : 61;
3244 pn->mtu = htole16(pcb->mtu);
3245 pn->max_retrans = 0;
3247 if (pcb->flags & NG_BTSOCKET_RFCOMM_DLC_CFC) {
3248 pn->flow_control = 0xf0;
3249 pn->credits = pcb->rx_cred;
3251 pn->flow_control = 0;
3255 NG_BTSOCKET_RFCOMM_INFO(
3256 "%s: Sending PN dlci=%d, state=%d, flags=%#x, mtu=%d, flow_control=%#x, " \
3257 "credits=%d\n", __func__, pcb->dlci, pcb->state, pcb->flags, pcb->mtu,
3258 pn->flow_control, pn->credits);
3260 return (ng_btsocket_rfcomm_send_uih(pcb->session,
3261 RFCOMM_MKADDRESS(INITIATOR(pcb->session), 0), 0, 0, m));
3262 } /* ng_btsocket_rfcomm_send_pn */
3265 * Calculate and send credits based on available space in receive buffer
3269 ng_btsocket_rfcomm_send_credits(ng_btsocket_rfcomm_pcb_p pcb)
3274 KKASSERT(lockowned(&pcb->pcb_lock) != 0);
3275 KKASSERT(lockowned(&pcb->session->session_lock) != 0);
3277 NG_BTSOCKET_RFCOMM_INFO(
3278 "%s: Sending more credits, dlci=%d, state=%d, flags=%#x, mtu=%d, " \
3279 "space=%ld, tx_cred=%d, rx_cred=%d\n",
3280 __func__, pcb->dlci, pcb->state, pcb->flags, pcb->mtu,
3281 ssb_space(&pcb->so->so_rcv), pcb->tx_cred, pcb->rx_cred);
3283 credits = ssb_space(&pcb->so->so_rcv) / pcb->mtu;
3285 if (pcb->rx_cred + credits > RFCOMM_MAX_CREDITS)
3286 credits = RFCOMM_MAX_CREDITS - pcb->rx_cred;
3288 error = ng_btsocket_rfcomm_send_uih(
3290 RFCOMM_MKADDRESS(INITIATOR(pcb->session),
3291 pcb->dlci), 1, credits, NULL);
3293 pcb->rx_cred += credits;
3295 NG_BTSOCKET_RFCOMM_INFO(
3296 "%s: Gave remote side %d more credits, dlci=%d, state=%d, flags=%#x, " \
3297 "rx_cred=%d, tx_cred=%d\n", __func__, credits, pcb->dlci, pcb->state,
3298 pcb->flags, pcb->rx_cred, pcb->tx_cred);
3300 NG_BTSOCKET_RFCOMM_ERR(
3301 "%s: Could not send credits, error=%d, dlci=%d, state=%d, flags=%#x, " \
3302 "mtu=%d, space=%ld, tx_cred=%d, rx_cred=%d\n",
3303 __func__, error, pcb->dlci, pcb->state,
3304 pcb->flags, pcb->mtu, ssb_space(&pcb->so->so_rcv),
3305 pcb->tx_cred, pcb->rx_cred);
3309 } /* ng_btsocket_rfcomm_send_credits */
3311 /*****************************************************************************
3312 *****************************************************************************
3314 *****************************************************************************
3315 *****************************************************************************/
3318 * Send data from socket send buffer
3319 * Caller must hold pcb->pcb_mtx and pcb->session->session_mtx
3323 ng_btsocket_rfcomm_pcb_send(ng_btsocket_rfcomm_pcb_p pcb, int limit)
3325 struct mbuf *m = NULL;
3326 int sent, length, error;
3328 KKASSERT(lockowned(&pcb->session->session_lock) != 0);
3329 KKASSERT(lockowned(&pcb->pcb_lock) != 0);
3331 if (pcb->flags & NG_BTSOCKET_RFCOMM_DLC_CFC)
3332 limit = min(limit, pcb->tx_cred);
3333 else if (!(pcb->rmodem & RFCOMM_MODEM_FC))
3334 limit = min(limit, RFCOMM_MAX_CREDITS); /* XXX ??? */
3339 NG_BTSOCKET_RFCOMM_INFO(
3340 "%s: Could not send - remote flow control asserted, dlci=%d, flags=%#x, " \
3341 "rmodem=%#x, tx_cred=%d\n",
3342 __func__, pcb->dlci, pcb->flags, pcb->rmodem,
3348 for (error = 0, sent = 0; sent < limit; sent ++) {
3349 length = min(pcb->mtu, pcb->so->so_snd.sb.sb_cc);
3353 /* Get the chunk from the socket's send buffer */
3354 m = ng_btsocket_rfcomm_prepare_packet(&pcb->so->so_snd.sb,
3361 sbdrop(&pcb->so->so_snd.sb, length);
3363 error = ng_btsocket_rfcomm_send_uih(pcb->session,
3364 RFCOMM_MKADDRESS(INITIATOR(pcb->session),
3365 pcb->dlci), 0, 0, m);
3370 if (pcb->flags & NG_BTSOCKET_RFCOMM_DLC_CFC)
3371 pcb->tx_cred -= sent;
3373 if (error == 0 && sent > 0) {
3374 pcb->flags &= ~NG_BTSOCKET_RFCOMM_DLC_SENDING;
3379 } /* ng_btsocket_rfcomm_pcb_send */
3382 * Unlink and disconnect DLC. If ng_btsocket_rfcomm_pcb_kill() returns
3383 * non zero value than socket has no reference and has to be detached.
3384 * Caller must hold pcb->pcb_mtx and pcb->session->session_mtx
3388 ng_btsocket_rfcomm_pcb_kill(ng_btsocket_rfcomm_pcb_p pcb, int error)
3390 ng_btsocket_rfcomm_session_p s = pcb->session;
3392 NG_BTSOCKET_RFCOMM_INFO(
3393 "%s: Killing DLC, so=%p, dlci=%d, state=%d, flags=%#x, error=%d\n",
3394 __func__, pcb->so, pcb->dlci, pcb->state, pcb->flags, error);
3396 if (pcb->session == NULL)
3397 panic("%s: DLC without session, pcb=%p, state=%d, flags=%#x",
3398 __func__, pcb, pcb->state, pcb->flags);
3400 KKASSERT(lockowned(&pcb->session->session_lock) != 0);
3401 KKASSERT(lockowned(&pcb->pcb_lock) != 0);
3403 if (pcb->flags & NG_BTSOCKET_RFCOMM_DLC_TIMO)
3404 ng_btsocket_rfcomm_untimeout(pcb);
3406 /* Detach DLC from the session. Does not matter which state DLC in */
3407 LIST_REMOVE(pcb, session_next);
3408 pcb->session = NULL;
3410 /* Change DLC state and wakeup all sleepers */
3411 pcb->state = NG_BTSOCKET_RFCOMM_DLC_CLOSED;
3412 pcb->so->so_error = error;
3413 soisdisconnected(pcb->so);
3414 wakeup(&pcb->state);
3416 /* Check if we have any DLCs left on the session */
3417 if (LIST_EMPTY(&s->dlcs) && INITIATOR(s)) {
3418 NG_BTSOCKET_RFCOMM_INFO(
3419 "%s: Disconnecting session, state=%d, flags=%#x, mtu=%d\n",
3420 __func__, s->state, s->flags, s->mtu);
3423 case NG_BTSOCKET_RFCOMM_SESSION_CLOSED:
3424 case NG_BTSOCKET_RFCOMM_SESSION_DISCONNECTING:
3426 * Do not have to do anything here. We can get here
3427 * when L2CAP connection was terminated or we have
3428 * received DISC on multiplexor channel
3432 case NG_BTSOCKET_RFCOMM_SESSION_OPEN:
3433 /* Send DISC on multiplexor channel */
3434 error = ng_btsocket_rfcomm_send_command(s,
3435 RFCOMM_FRAME_DISC, 0);
3437 s->state = NG_BTSOCKET_RFCOMM_SESSION_DISCONNECTING;
3442 case NG_BTSOCKET_RFCOMM_SESSION_CONNECTING:
3443 case NG_BTSOCKET_RFCOMM_SESSION_CONNECTED:
3444 s->state = NG_BTSOCKET_RFCOMM_SESSION_CLOSED;
3447 /* case NG_BTSOCKET_RFCOMM_SESSION_LISTENING: */
3449 panic("%s: Invalid session state=%d, flags=%#x",
3450 __func__, s->state, s->flags);
3454 ng_btsocket_rfcomm_task_wakeup();
3456 } /* ng_btsocket_rfcomm_pcb_kill */
3459 * Look for given dlci for given RFCOMM session. Caller must hold s->session_mtx
3462 static ng_btsocket_rfcomm_pcb_p
3463 ng_btsocket_rfcomm_pcb_by_dlci(ng_btsocket_rfcomm_session_p s, int dlci)
3465 ng_btsocket_rfcomm_pcb_p pcb = NULL;
3467 KKASSERT(lockowned(&s->session_lock) != 0);
3469 LIST_FOREACH(pcb, &s->dlcs, session_next)
3470 if (pcb->dlci == dlci)
3474 } /* ng_btsocket_rfcomm_pcb_by_dlci */
3477 * Look for socket that listens on given src address and given channel
3480 static ng_btsocket_rfcomm_pcb_p
3481 ng_btsocket_rfcomm_pcb_listener(bdaddr_p src, int channel)
3483 ng_btsocket_rfcomm_pcb_p pcb = NULL, pcb1 = NULL;
3485 lockmgr(&ng_btsocket_rfcomm_sockets_lock, LK_EXCLUSIVE);
3487 LIST_FOREACH(pcb, &ng_btsocket_rfcomm_sockets, next) {
3488 if (pcb->channel != channel ||
3489 !(pcb->so->so_options & SO_ACCEPTCONN))
3492 if (bcmp(&pcb->src, src, sizeof(*src)) == 0)
3495 if (bcmp(&pcb->src, NG_HCI_BDADDR_ANY, sizeof(bdaddr_t)) == 0)
3499 lockmgr(&ng_btsocket_rfcomm_sockets_lock, LK_RELEASE);
3501 return ((pcb != NULL)? pcb : pcb1);
3502 } /* ng_btsocket_rfcomm_pcb_listener */
3504 /*****************************************************************************
3505 *****************************************************************************
3507 *****************************************************************************
3508 *****************************************************************************/
3511 * Set timeout. Caller MUST hold pcb_mtx
3515 ng_btsocket_rfcomm_timeout(ng_btsocket_rfcomm_pcb_p pcb)
3517 KKASSERT(lockowned(&pcb->pcb_lock) != 0);
3519 if (!(pcb->flags & NG_BTSOCKET_RFCOMM_DLC_TIMO)) {
3520 pcb->flags |= NG_BTSOCKET_RFCOMM_DLC_TIMO;
3521 pcb->flags &= ~NG_BTSOCKET_RFCOMM_DLC_TIMEDOUT;
3522 callout_reset(&pcb->timo, ng_btsocket_rfcomm_timo * hz,
3523 ng_btsocket_rfcomm_process_timeout, pcb);
3525 panic("%s: Duplicated socket timeout?!", __func__);
3526 } /* ng_btsocket_rfcomm_timeout */
3529 * Unset pcb timeout. Caller MUST hold pcb_mtx
3533 ng_btsocket_rfcomm_untimeout(ng_btsocket_rfcomm_pcb_p pcb)
3535 KKASSERT(lockowned(&pcb->pcb_lock) != 0);
3537 if (pcb->flags & NG_BTSOCKET_RFCOMM_DLC_TIMO) {
3538 callout_stop(&pcb->timo);
3539 pcb->flags &= ~NG_BTSOCKET_RFCOMM_DLC_TIMO;
3540 pcb->flags &= ~NG_BTSOCKET_RFCOMM_DLC_TIMEDOUT;
3542 panic("%s: No socket timeout?!", __func__);
3543 } /* ng_btsocket_rfcomm_timeout */
3546 * Process pcb timeout
3550 ng_btsocket_rfcomm_process_timeout(void *xpcb)
3552 ng_btsocket_rfcomm_pcb_p pcb = (ng_btsocket_rfcomm_pcb_p) xpcb;
3554 lockmgr(&pcb->pcb_lock, LK_EXCLUSIVE);
3556 NG_BTSOCKET_RFCOMM_INFO(
3557 "%s: Timeout, so=%p, dlci=%d, state=%d, flags=%#x\n",
3558 __func__, pcb->so, pcb->dlci, pcb->state, pcb->flags);
3560 pcb->flags &= ~NG_BTSOCKET_RFCOMM_DLC_TIMO;
3561 pcb->flags |= NG_BTSOCKET_RFCOMM_DLC_TIMEDOUT;
3563 switch (pcb->state) {
3564 case NG_BTSOCKET_RFCOMM_DLC_CONFIGURING:
3565 case NG_BTSOCKET_RFCOMM_DLC_CONNECTING:
3566 pcb->state = NG_BTSOCKET_RFCOMM_DLC_DISCONNECTING;
3569 case NG_BTSOCKET_RFCOMM_DLC_W4_CONNECT:
3570 case NG_BTSOCKET_RFCOMM_DLC_DISCONNECTING:
3575 "%s: DLC timeout in invalid state, dlci=%d, state=%d, flags=%#x\n",
3576 __func__, pcb->dlci, pcb->state, pcb->flags);
3580 ng_btsocket_rfcomm_task_wakeup();
3582 lockmgr(&pcb->pcb_lock, LK_RELEASE);
3583 } /* ng_btsocket_rfcomm_process_timeout */
3586 * Get up to length bytes from the socket buffer
3589 static struct mbuf *
3590 ng_btsocket_rfcomm_prepare_packet(struct sockbuf *sb, int length)
3592 struct mbuf *top = NULL, *m = NULL, *n = NULL, *nextpkt = NULL;
3593 int mlen, noff, len;
3595 MGETHDR(top, M_NOWAIT, MT_DATA);
3599 top->m_pkthdr.len = length;
3605 nextpkt = n->m_nextpkt;
3608 while (length > 0 && n != NULL) {
3609 len = min(mlen - m->m_len, n->m_len - noff);
3613 bcopy(mtod(n, caddr_t)+noff, mtod(m, caddr_t)+m->m_len, len);
3618 if (length > 0 && m->m_len == mlen) {
3619 MGET(m->m_next, M_NOWAIT, MT_DATA);
3620 if (m->m_next == NULL) {
3630 if (noff == n->m_len) {
3637 nextpkt = (n != NULL)? n->m_nextpkt : NULL;
3642 panic("%s: length=%d", __func__, length);
3643 if (length > 0 && n == NULL)
3644 panic("%s: bogus length=%d, n=%p", __func__, length, n);
3647 } /* ng_btsocket_rfcomm_prepare_packet */