FreeBSD kernel netgraph code
ng_btsocket_rfcomm.c
Go to the documentation of this file.
1/*
2 * ng_btsocket_rfcomm.c
3 */
4
5/*-
6 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
7 *
8 * Copyright (c) 2001-2003 Maksim Yevmenkin <m_evmenkin@yahoo.com>
9 * All rights reserved.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * SUCH DAMAGE.
31 *
32 * $Id: ng_btsocket_rfcomm.c,v 1.28 2003/09/14 23:29:06 max Exp $
33 * $FreeBSD$
34 */
35
36#include <sys/param.h>
37#include <sys/systm.h>
38#include <sys/bitstring.h>
39#include <sys/domain.h>
40#include <sys/endian.h>
41#include <sys/errno.h>
42#include <sys/filedesc.h>
43#include <sys/ioccom.h>
44#include <sys/kernel.h>
45#include <sys/lock.h>
46#include <sys/malloc.h>
47#include <sys/mbuf.h>
48#include <sys/mutex.h>
49#include <sys/proc.h>
50#include <sys/protosw.h>
51#include <sys/queue.h>
52#include <sys/socket.h>
53#include <sys/socketvar.h>
54#include <sys/sysctl.h>
55#include <sys/taskqueue.h>
56#include <sys/uio.h>
57
58#include <net/vnet.h>
59
60#include <netgraph/ng_message.h>
61#include <netgraph/netgraph.h>
68
69/* MALLOC define */
70#ifdef NG_SEPARATE_MALLOC
71static MALLOC_DEFINE(M_NETGRAPH_BTSOCKET_RFCOMM, "netgraph_btsocks_rfcomm",
72 "Netgraph Bluetooth RFCOMM sockets");
73#else
74#define M_NETGRAPH_BTSOCKET_RFCOMM M_NETGRAPH
75#endif /* NG_SEPARATE_MALLOC */
76
77/* Debug */
78#define NG_BTSOCKET_RFCOMM_INFO \
79 if (ng_btsocket_rfcomm_debug_level >= NG_BTSOCKET_INFO_LEVEL && \
80 ppsratecheck(&ng_btsocket_rfcomm_lasttime, &ng_btsocket_rfcomm_curpps, 1)) \
81 printf
82
83#define NG_BTSOCKET_RFCOMM_WARN \
84 if (ng_btsocket_rfcomm_debug_level >= NG_BTSOCKET_WARN_LEVEL && \
85 ppsratecheck(&ng_btsocket_rfcomm_lasttime, &ng_btsocket_rfcomm_curpps, 1)) \
86 printf
87
88#define NG_BTSOCKET_RFCOMM_ERR \
89 if (ng_btsocket_rfcomm_debug_level >= NG_BTSOCKET_ERR_LEVEL && \
90 ppsratecheck(&ng_btsocket_rfcomm_lasttime, &ng_btsocket_rfcomm_curpps, 1)) \
91 printf
92
93#define NG_BTSOCKET_RFCOMM_ALERT \
94 if (ng_btsocket_rfcomm_debug_level >= NG_BTSOCKET_ALERT_LEVEL && \
95 ppsratecheck(&ng_btsocket_rfcomm_lasttime, &ng_btsocket_rfcomm_curpps, 1)) \
96 printf
97
98#define ALOT 0x7fff
99
100/* Local prototypes */
102 (struct socket *so, void *arg, int waitflag);
104 (void *ctx, int pending);
107#define ng_btsocket_rfcomm_task_wakeup() \
108 taskqueue_enqueue(taskqueue_swi_giant, &ng_btsocket_rfcomm_task)
109
111 (ng_btsocket_rfcomm_session_p s, int channel);
114
116 (ng_btsocket_rfcomm_session_p *sp, struct socket *l2so,
117 bdaddr_p src, bdaddr_p dst, struct thread *td);
131 (bdaddr_p src, bdaddr_p dst);
132
134 (ng_btsocket_rfcomm_session_p s, struct mbuf *m0);
144 (ng_btsocket_rfcomm_session_p s, int dlci, int pf, struct mbuf *m0);
146 (ng_btsocket_rfcomm_session_p s, struct mbuf *m0);
148 (ng_btsocket_rfcomm_session_p s, struct mbuf *m0);
150 (ng_btsocket_rfcomm_session_p s, struct mbuf *m0);
152 (ng_btsocket_rfcomm_session_p s, struct mbuf *m0);
154 (ng_btsocket_rfcomm_session_p s, struct mbuf *m0);
156 (ng_btsocket_rfcomm_session_p s, struct mbuf *m0);
158 (ng_btsocket_rfcomm_session_p s, struct mbuf *m0);
160 (ng_btsocket_rfcomm_pcb_p pcb, u_int8_t cr, u_int8_t flow_control,
161 u_int8_t credits, u_int16_t mtu);
162
164 (ng_btsocket_rfcomm_session_p s, u_int8_t type, u_int8_t dlci);
166 (ng_btsocket_rfcomm_session_p s, u_int8_t address, u_int8_t pf,
167 u_int8_t credits, struct mbuf *data);
174
176 (ng_btsocket_rfcomm_pcb_p pcb, int limit);
178 (ng_btsocket_rfcomm_pcb_p pcb, int error);
182 (bdaddr_p src, int channel);
183
189 (void *xpcb);
190
191static struct mbuf * ng_btsocket_rfcomm_prepare_packet
192 (struct sockbuf *sb, int length);
193
194/* Globals */
195extern int ifqmaxlen;
197static u_int32_t ng_btsocket_rfcomm_timo;
199static LIST_HEAD(, ng_btsocket_rfcomm_session) ng_btsocket_rfcomm_sessions;
200static struct mtx ng_btsocket_rfcomm_sessions_mtx;
201static LIST_HEAD(, ng_btsocket_rfcomm_pcb) ng_btsocket_rfcomm_sockets;
202static struct mtx ng_btsocket_rfcomm_sockets_mtx;
203static struct timeval ng_btsocket_rfcomm_lasttime;
204static int ng_btsocket_rfcomm_curpps;
205
206/* Sysctl tree */
207SYSCTL_DECL(_net_bluetooth_rfcomm_sockets);
208static SYSCTL_NODE(_net_bluetooth_rfcomm_sockets, OID_AUTO, stream,
209 CTLFLAG_RW | CTLFLAG_MPSAFE, 0,
210 "Bluetooth STREAM RFCOMM sockets family");
211SYSCTL_UINT(_net_bluetooth_rfcomm_sockets_stream, OID_AUTO, debug_level,
212 CTLFLAG_RW,
214 "Bluetooth STREAM RFCOMM sockets debug level");
215SYSCTL_UINT(_net_bluetooth_rfcomm_sockets_stream, OID_AUTO, timeout,
216 CTLFLAG_RW,
218 "Bluetooth STREAM RFCOMM sockets timeout");
219
220/*****************************************************************************
221 *****************************************************************************
222 ** RFCOMM CRC
223 *****************************************************************************
224 *****************************************************************************/
225
226static u_int8_t ng_btsocket_rfcomm_crc_table[256] = {
227 0x00, 0x91, 0xe3, 0x72, 0x07, 0x96, 0xe4, 0x75,
228 0x0e, 0x9f, 0xed, 0x7c, 0x09, 0x98, 0xea, 0x7b,
229 0x1c, 0x8d, 0xff, 0x6e, 0x1b, 0x8a, 0xf8, 0x69,
230 0x12, 0x83, 0xf1, 0x60, 0x15, 0x84, 0xf6, 0x67,
231
232 0x38, 0xa9, 0xdb, 0x4a, 0x3f, 0xae, 0xdc, 0x4d,
233 0x36, 0xa7, 0xd5, 0x44, 0x31, 0xa0, 0xd2, 0x43,
234 0x24, 0xb5, 0xc7, 0x56, 0x23, 0xb2, 0xc0, 0x51,
235 0x2a, 0xbb, 0xc9, 0x58, 0x2d, 0xbc, 0xce, 0x5f,
236
237 0x70, 0xe1, 0x93, 0x02, 0x77, 0xe6, 0x94, 0x05,
238 0x7e, 0xef, 0x9d, 0x0c, 0x79, 0xe8, 0x9a, 0x0b,
239 0x6c, 0xfd, 0x8f, 0x1e, 0x6b, 0xfa, 0x88, 0x19,
240 0x62, 0xf3, 0x81, 0x10, 0x65, 0xf4, 0x86, 0x17,
241
242 0x48, 0xd9, 0xab, 0x3a, 0x4f, 0xde, 0xac, 0x3d,
243 0x46, 0xd7, 0xa5, 0x34, 0x41, 0xd0, 0xa2, 0x33,
244 0x54, 0xc5, 0xb7, 0x26, 0x53, 0xc2, 0xb0, 0x21,
245 0x5a, 0xcb, 0xb9, 0x28, 0x5d, 0xcc, 0xbe, 0x2f,
246
247 0xe0, 0x71, 0x03, 0x92, 0xe7, 0x76, 0x04, 0x95,
248 0xee, 0x7f, 0x0d, 0x9c, 0xe9, 0x78, 0x0a, 0x9b,
249 0xfc, 0x6d, 0x1f, 0x8e, 0xfb, 0x6a, 0x18, 0x89,
250 0xf2, 0x63, 0x11, 0x80, 0xf5, 0x64, 0x16, 0x87,
251
252 0xd8, 0x49, 0x3b, 0xaa, 0xdf, 0x4e, 0x3c, 0xad,
253 0xd6, 0x47, 0x35, 0xa4, 0xd1, 0x40, 0x32, 0xa3,
254 0xc4, 0x55, 0x27, 0xb6, 0xc3, 0x52, 0x20, 0xb1,
255 0xca, 0x5b, 0x29, 0xb8, 0xcd, 0x5c, 0x2e, 0xbf,
256
257 0x90, 0x01, 0x73, 0xe2, 0x97, 0x06, 0x74, 0xe5,
258 0x9e, 0x0f, 0x7d, 0xec, 0x99, 0x08, 0x7a, 0xeb,
259 0x8c, 0x1d, 0x6f, 0xfe, 0x8b, 0x1a, 0x68, 0xf9,
260 0x82, 0x13, 0x61, 0xf0, 0x85, 0x14, 0x66, 0xf7,
261
262 0xa8, 0x39, 0x4b, 0xda, 0xaf, 0x3e, 0x4c, 0xdd,
263 0xa6, 0x37, 0x45, 0xd4, 0xa1, 0x30, 0x42, 0xd3,
264 0xb4, 0x25, 0x57, 0xc6, 0xb3, 0x22, 0x50, 0xc1,
265 0xba, 0x2b, 0x59, 0xc8, 0xbd, 0x2c, 0x5e, 0xcf
266};
267
268/* CRC */
269static u_int8_t
271{
272 u_int8_t crc = 0xff;
273
274 while (length --)
275 crc = ng_btsocket_rfcomm_crc_table[crc ^ *data++];
276
277 return (crc);
278} /* ng_btsocket_rfcomm_crc */
279
280/* FCS on 2 bytes */
281static u_int8_t
283{
284 return (0xff - ng_btsocket_rfcomm_crc(data, 2));
285} /* ng_btsocket_rfcomm_fcs2 */
286
287/* FCS on 3 bytes */
288static u_int8_t
290{
291 return (0xff - ng_btsocket_rfcomm_crc(data, 3));
292} /* ng_btsocket_rfcomm_fcs3 */
293
294/*
295 * Check FCS
296 *
297 * From Bluetooth spec
298 *
299 * "... In 07.10, the frame check sequence (FCS) is calculated on different
300 * sets of fields for different frame types. These are the fields that the
301 * FCS are calculated on:
302 *
303 * For SABM, DISC, UA, DM frames: on Address, Control and length field.
304 * For UIH frames: on Address and Control field.
305 *
306 * (This is stated here for clarification, and to set the standard for RFCOMM;
307 * the fields included in FCS calculation have actually changed in version
308 * 7.0.0 of TS 07.10, but RFCOMM will not change the FCS calculation scheme
309 * from the one above.) ..."
310 */
311
312static int
313ng_btsocket_rfcomm_check_fcs(u_int8_t *data, int type, u_int8_t fcs)
314{
315 if (type != RFCOMM_FRAME_UIH)
316 return (ng_btsocket_rfcomm_fcs3(data) != fcs);
317
318 return (ng_btsocket_rfcomm_fcs2(data) != fcs);
319} /* ng_btsocket_rfcomm_check_fcs */
320
321/*****************************************************************************
322 *****************************************************************************
323 ** Socket interface
324 *****************************************************************************
325 *****************************************************************************/
326
327/*
328 * Initialize everything
329 */
330
331static void
332ng_btsocket_rfcomm_init(void *arg __unused)
333{
334
337
338 /* RFCOMM task */
339 TASK_INIT(&ng_btsocket_rfcomm_task, 0,
341
342 /* RFCOMM sessions list */
343 LIST_INIT(&ng_btsocket_rfcomm_sessions);
344 mtx_init(&ng_btsocket_rfcomm_sessions_mtx,
345 "btsocks_rfcomm_sessions_mtx", NULL, MTX_DEF);
346
347 /* RFCOMM sockets list */
348 LIST_INIT(&ng_btsocket_rfcomm_sockets);
349 mtx_init(&ng_btsocket_rfcomm_sockets_mtx,
350 "btsocks_rfcomm_sockets_mtx", NULL, MTX_DEF);
351} /* ng_btsocket_rfcomm_init */
352SYSINIT(ng_btsocket_rfcomm_init, SI_SUB_PROTO_DOMAIN, SI_ORDER_THIRD,
354
355/*
356 * Abort connection on socket
357 */
358
359void
360ng_btsocket_rfcomm_abort(struct socket *so)
361{
362
363 so->so_error = ECONNABORTED;
365} /* ng_btsocket_rfcomm_abort */
366
367void
368ng_btsocket_rfcomm_close(struct socket *so)
369{
370
372} /* ng_btsocket_rfcomm_close */
373
374/*
375 * Accept connection on socket. Nothing to do here, socket must be connected
376 * and ready, so just return peer address and be done with it.
377 */
378
379int
380ng_btsocket_rfcomm_accept(struct socket *so, struct sockaddr **nam)
381{
382 return (ng_btsocket_rfcomm_peeraddr(so, nam));
383} /* ng_btsocket_rfcomm_accept */
384
385/*
386 * Create and attach new socket
387 */
388
389int
390ng_btsocket_rfcomm_attach(struct socket *so, int proto, struct thread *td)
391{
393 int error;
394
395 /* Check socket and protocol */
396 if (so->so_type != SOCK_STREAM)
397 return (ESOCKTNOSUPPORT);
398
399#if 0 /* XXX sonewconn() calls "pru_attach" with proto == 0 */
400 if (proto != 0)
401 if (proto != BLUETOOTH_PROTO_RFCOMM)
402 return (EPROTONOSUPPORT);
403#endif /* XXX */
404
405 if (pcb != NULL)
406 return (EISCONN);
407
408 /* Reserve send and receive space if it is not reserved yet */
409 if ((so->so_snd.sb_hiwat == 0) || (so->so_rcv.sb_hiwat == 0)) {
410 error = soreserve(so, NG_BTSOCKET_RFCOMM_SENDSPACE,
412 if (error != 0)
413 return (error);
414 }
415
416 /* Allocate the PCB */
417 pcb = malloc(sizeof(*pcb),
418 M_NETGRAPH_BTSOCKET_RFCOMM, M_NOWAIT | M_ZERO);
419 if (pcb == NULL)
420 return (ENOMEM);
421
422 /* Link the PCB and the socket */
423 so->so_pcb = (caddr_t) pcb;
424 pcb->so = so;
425
426 /* Initialize PCB */
429
430 pcb->lmodem =
432
433 pcb->mtu = RFCOMM_DEFAULT_MTU;
434 pcb->tx_cred = 0;
436
437 mtx_init(&pcb->pcb_mtx, "btsocks_rfcomm_pcb_mtx", NULL, MTX_DEF);
438 callout_init_mtx(&pcb->timo, &pcb->pcb_mtx, 0);
439
440 /* Add the PCB to the list */
441 mtx_lock(&ng_btsocket_rfcomm_sockets_mtx);
442 LIST_INSERT_HEAD(&ng_btsocket_rfcomm_sockets, pcb, next);
443 mtx_unlock(&ng_btsocket_rfcomm_sockets_mtx);
444
445 return (0);
446} /* ng_btsocket_rfcomm_attach */
447
448/*
449 * Bind socket
450 */
451
452int
453ng_btsocket_rfcomm_bind(struct socket *so, struct sockaddr *nam,
454 struct thread *td)
455{
456 ng_btsocket_rfcomm_pcb_t *pcb = so2rfcomm_pcb(so), *pcb1;
457 struct sockaddr_rfcomm *sa = (struct sockaddr_rfcomm *) nam;
458
459 if (pcb == NULL)
460 return (EINVAL);
461
462 /* Verify address */
463 if (sa == NULL)
464 return (EINVAL);
465 if (sa->rfcomm_family != AF_BLUETOOTH)
466 return (EAFNOSUPPORT);
467 if (sa->rfcomm_len != sizeof(*sa))
468 return (EINVAL);
469 if (sa->rfcomm_channel > 30)
470 return (EINVAL);
471
472 mtx_lock(&pcb->pcb_mtx);
473
474 if (sa->rfcomm_channel != 0) {
475 mtx_lock(&ng_btsocket_rfcomm_sockets_mtx);
476
477 LIST_FOREACH(pcb1, &ng_btsocket_rfcomm_sockets, next) {
478 if (pcb1->channel == sa->rfcomm_channel &&
479 bcmp(&pcb1->src, &sa->rfcomm_bdaddr,
480 sizeof(pcb1->src)) == 0) {
481 mtx_unlock(&ng_btsocket_rfcomm_sockets_mtx);
482 mtx_unlock(&pcb->pcb_mtx);
483
484 return (EADDRINUSE);
485 }
486 }
487
488 mtx_unlock(&ng_btsocket_rfcomm_sockets_mtx);
489 }
490
491 bcopy(&sa->rfcomm_bdaddr, &pcb->src, sizeof(pcb->src));
492 pcb->channel = sa->rfcomm_channel;
493
494 mtx_unlock(&pcb->pcb_mtx);
495
496 return (0);
497} /* ng_btsocket_rfcomm_bind */
498
499/*
500 * Connect socket
501 */
502
503int
504ng_btsocket_rfcomm_connect(struct socket *so, struct sockaddr *nam,
505 struct thread *td)
506{
508 struct sockaddr_rfcomm *sa = (struct sockaddr_rfcomm *) nam;
510 struct socket *l2so = NULL;
511 int dlci, error = 0;
512
513 if (pcb == NULL)
514 return (EINVAL);
515
516 /* Verify address */
517 if (sa == NULL)
518 return (EINVAL);
519 if (sa->rfcomm_family != AF_BLUETOOTH)
520 return (EAFNOSUPPORT);
521 if (sa->rfcomm_len != sizeof(*sa))
522 return (EINVAL);
523 if (sa->rfcomm_channel > 30)
524 return (EINVAL);
525 if (sa->rfcomm_channel == 0 ||
526 bcmp(&sa->rfcomm_bdaddr, NG_HCI_BDADDR_ANY, sizeof(bdaddr_t)) == 0)
527 return (EDESTADDRREQ);
528
529 /*
530 * Note that we will not check for errors in socreate() because
531 * if we failed to create L2CAP socket at this point we still
532 * might have already open session.
533 */
534
535 error = socreate(PF_BLUETOOTH, &l2so, SOCK_SEQPACKET,
536 BLUETOOTH_PROTO_L2CAP, td->td_ucred, td);
537
538 /*
539 * Look for session between "pcb->src" and "sa->rfcomm_bdaddr" (dst)
540 */
541
542 mtx_lock(&ng_btsocket_rfcomm_sessions_mtx);
543
545 if (s == NULL) {
546 /*
547 * We need to create new RFCOMM session. Check if we have L2CAP
548 * socket. If l2so == NULL then error has the error code from
549 * socreate()
550 */
551
552 if (l2so == NULL) {
553 mtx_unlock(&ng_btsocket_rfcomm_sessions_mtx);
554 return (error);
555 }
556
557 error = ng_btsocket_rfcomm_session_create(&s, l2so,
558 &pcb->src, &sa->rfcomm_bdaddr, td);
559 if (error != 0) {
560 mtx_unlock(&ng_btsocket_rfcomm_sessions_mtx);
561 soclose(l2so);
562
563 return (error);
564 }
565 } else if (l2so != NULL)
566 soclose(l2so); /* we don't need new L2CAP socket */
567
568 /*
569 * Check if we already have the same DLCI the same session
570 */
571
572 mtx_lock(&s->session_mtx);
573 mtx_lock(&pcb->pcb_mtx);
574
576
577 if (ng_btsocket_rfcomm_pcb_by_dlci(s, dlci) != NULL) {
578 mtx_unlock(&pcb->pcb_mtx);
579 mtx_unlock(&s->session_mtx);
580 mtx_unlock(&ng_btsocket_rfcomm_sessions_mtx);
581
582 return (EBUSY);
583 }
584
585 /*
586 * Check session state and if its not acceptable then refuse connection
587 */
588
589 switch (s->state) {
593 /*
594 * Update destination address and channel and attach
595 * DLC to the session
596 */
597
598 bcopy(&sa->rfcomm_bdaddr, &pcb->dst, sizeof(pcb->dst));
599 pcb->channel = sa->rfcomm_channel;
600 pcb->dlci = dlci;
601
602 LIST_INSERT_HEAD(&s->dlcs, pcb, session_next);
603 pcb->session = s;
604
606 soisconnecting(pcb->so);
607
609 pcb->mtu = s->mtu;
610 bcopy(&so2l2cap_pcb(s->l2so)->src, &pcb->src,
611 sizeof(pcb->src));
612
614
615 error = ng_btsocket_rfcomm_send_pn(pcb);
616 if (error == 0)
618 } else
620 break;
621
622 default:
623 error = ECONNRESET;
624 break;
625 }
626
627 mtx_unlock(&pcb->pcb_mtx);
628 mtx_unlock(&s->session_mtx);
629 mtx_unlock(&ng_btsocket_rfcomm_sessions_mtx);
630
631 return (error);
632} /* ng_btsocket_rfcomm_connect */
633
634/*
635 * Process ioctl's calls on socket.
636 * XXX FIXME this should provide interface to the RFCOMM multiplexor channel
637 */
638
639int
640ng_btsocket_rfcomm_control(struct socket *so, u_long cmd, caddr_t data,
641 struct ifnet *ifp, struct thread *td)
642{
643 return (EINVAL);
644} /* ng_btsocket_rfcomm_control */
645
646/*
647 * Process getsockopt/setsockopt system calls
648 */
649
650int
651ng_btsocket_rfcomm_ctloutput(struct socket *so, struct sockopt *sopt)
652{
654 struct ng_btsocket_rfcomm_fc_info fcinfo;
655 int error = 0;
656
657 if (pcb == NULL)
658 return (EINVAL);
659 if (sopt->sopt_level != SOL_RFCOMM)
660 return (0);
661
662 mtx_lock(&pcb->pcb_mtx);
663
664 switch (sopt->sopt_dir) {
665 case SOPT_GET:
666 switch (sopt->sopt_name) {
667 case SO_RFCOMM_MTU:
668 error = sooptcopyout(sopt, &pcb->mtu, sizeof(pcb->mtu));
669 break;
670
672 fcinfo.lmodem = pcb->lmodem;
673 fcinfo.rmodem = pcb->rmodem;
674 fcinfo.tx_cred = pcb->tx_cred;
675 fcinfo.rx_cred = pcb->rx_cred;
676 fcinfo.cfc = (pcb->flags & NG_BTSOCKET_RFCOMM_DLC_CFC)?
677 1 : 0;
678 fcinfo.reserved = 0;
679
680 error = sooptcopyout(sopt, &fcinfo, sizeof(fcinfo));
681 break;
682
683 default:
684 error = ENOPROTOOPT;
685 break;
686 }
687 break;
688
689 case SOPT_SET:
690 switch (sopt->sopt_name) {
691 default:
692 error = ENOPROTOOPT;
693 break;
694 }
695 break;
696
697 default:
698 error = EINVAL;
699 break;
700 }
701
702 mtx_unlock(&pcb->pcb_mtx);
703
704 return (error);
705} /* ng_btsocket_rfcomm_ctloutput */
706
707/*
708 * Detach and destroy socket
709 */
710
711void
713{
715
716 KASSERT(pcb != NULL, ("ng_btsocket_rfcomm_detach: pcb == NULL"));
717
718 mtx_lock(&pcb->pcb_mtx);
719
720 switch (pcb->state) {
725 /* XXX What to do with pending request? */
728
731 else
733
735 break;
736
739 break;
740 }
741
743 msleep(&pcb->state, &pcb->pcb_mtx, PZERO, "rf_det", 0);
744
745 if (pcb->session != NULL)
746 panic("%s: pcb->session != NULL\n", __func__);
748 panic("%s: timeout on closed DLC, flags=%#x\n",
749 __func__, pcb->flags);
750
751 mtx_lock(&ng_btsocket_rfcomm_sockets_mtx);
752 LIST_REMOVE(pcb, next);
753 mtx_unlock(&ng_btsocket_rfcomm_sockets_mtx);
754
755 mtx_unlock(&pcb->pcb_mtx);
756
757 mtx_destroy(&pcb->pcb_mtx);
758 bzero(pcb, sizeof(*pcb));
760
761 soisdisconnected(so);
762 so->so_pcb = NULL;
763} /* ng_btsocket_rfcomm_detach */
764
765/*
766 * Disconnect socket
767 */
768
769int
771{
773
774 if (pcb == NULL)
775 return (EINVAL);
776
777 mtx_lock(&pcb->pcb_mtx);
778
780 mtx_unlock(&pcb->pcb_mtx);
781 return (EINPROGRESS);
782 }
783
784 /* XXX What to do with pending request? */
787
788 switch (pcb->state) {
789 case NG_BTSOCKET_RFCOMM_DLC_CONFIGURING: /* XXX can we get here? */
790 case NG_BTSOCKET_RFCOMM_DLC_CONNECTING: /* XXX can we get here? */
792
793 /*
794 * Just change DLC state and enqueue RFCOMM task. It will
795 * queue and send DISC on the DLC.
796 */
797
799 soisdisconnecting(so);
800
802 break;
803
806 break;
807
808 default:
809 panic("%s: Invalid DLC state=%d, flags=%#x\n",
810 __func__, pcb->state, pcb->flags);
811 break;
812 }
813
814 mtx_unlock(&pcb->pcb_mtx);
815
816 return (0);
817} /* ng_btsocket_rfcomm_disconnect */
818
819/*
820 * Listen on socket. First call to listen() will create listening RFCOMM session
821 */
822
823int
824ng_btsocket_rfcomm_listen(struct socket *so, int backlog, struct thread *td)
825{
828 struct socket *l2so = NULL;
829 int error, socreate_error, usedchannels;
830
831 if (pcb == NULL)
832 return (EINVAL);
833 if (pcb->channel > 30)
834 return (EADDRNOTAVAIL);
835
836 usedchannels = 0;
837
838 mtx_lock(&pcb->pcb_mtx);
839
840 if (pcb->channel == 0) {
841 mtx_lock(&ng_btsocket_rfcomm_sockets_mtx);
842
843 LIST_FOREACH(pcb1, &ng_btsocket_rfcomm_sockets, next)
844 if (pcb1->channel != 0 &&
845 bcmp(&pcb1->src, &pcb->src, sizeof(pcb->src)) == 0)
846 usedchannels |= (1 << (pcb1->channel - 1));
847
848 for (pcb->channel = 30; pcb->channel > 0; pcb->channel --)
849 if (!(usedchannels & (1 << (pcb->channel - 1))))
850 break;
851
852 if (pcb->channel == 0) {
853 mtx_unlock(&ng_btsocket_rfcomm_sockets_mtx);
854 mtx_unlock(&pcb->pcb_mtx);
855
856 return (EADDRNOTAVAIL);
857 }
858
859 mtx_unlock(&ng_btsocket_rfcomm_sockets_mtx);
860 }
861
862 mtx_unlock(&pcb->pcb_mtx);
863
864 /*
865 * Note that we will not check for errors in socreate() because
866 * if we failed to create L2CAP socket at this point we still
867 * might have already open session.
868 */
869
870 socreate_error = socreate(PF_BLUETOOTH, &l2so, SOCK_SEQPACKET,
871 BLUETOOTH_PROTO_L2CAP, td->td_ucred, td);
872
873 /*
874 * Transition the socket and session into the LISTENING state. Check
875 * for collisions first, as there can only be one.
876 */
877 mtx_lock(&ng_btsocket_rfcomm_sessions_mtx);
878 SOCK_LOCK(so);
879 error = solisten_proto_check(so);
880 SOCK_UNLOCK(so);
881 if (error != 0)
882 goto out;
883
884 LIST_FOREACH(s, &ng_btsocket_rfcomm_sessions, next)
886 break;
887
888 if (s == NULL) {
889 /*
890 * We need to create default RFCOMM session. Check if we have
891 * L2CAP socket. If l2so == NULL then error has the error code
892 * from socreate()
893 */
894 if (l2so == NULL) {
895 solisten_proto_abort(so);
896 error = socreate_error;
897 goto out;
898 }
899
900 /*
901 * Create default listen RFCOMM session. The default RFCOMM
902 * session will listen on ANY address.
903 *
904 * XXX FIXME Note that currently there is no way to adjust MTU
905 * for the default session.
906 */
907 error = ng_btsocket_rfcomm_session_create(&s, l2so,
908 NG_HCI_BDADDR_ANY, NULL, td);
909 if (error != 0) {
910 solisten_proto_abort(so);
911 goto out;
912 }
913 l2so = NULL;
914 }
915 SOCK_LOCK(so);
916 solisten_proto(so, backlog);
917 SOCK_UNLOCK(so);
918out:
919 mtx_unlock(&ng_btsocket_rfcomm_sessions_mtx);
920 /*
921 * If we still have an l2so reference here, it's unneeded, so release
922 * it.
923 */
924 if (l2so != NULL)
925 soclose(l2so);
926 return (error);
927} /* ng_btsocket_listen */
928
929/*
930 * Get peer address
931 */
932
933int
934ng_btsocket_rfcomm_peeraddr(struct socket *so, struct sockaddr **nam)
935{
937 struct sockaddr_rfcomm sa;
938
939 if (pcb == NULL)
940 return (EINVAL);
941
942 bcopy(&pcb->dst, &sa.rfcomm_bdaddr, sizeof(sa.rfcomm_bdaddr));
943 sa.rfcomm_channel = pcb->channel;
944 sa.rfcomm_len = sizeof(sa);
945 sa.rfcomm_family = AF_BLUETOOTH;
946
947 *nam = sodupsockaddr((struct sockaddr *) &sa, M_NOWAIT);
948
949 return ((*nam == NULL)? ENOMEM : 0);
950} /* ng_btsocket_rfcomm_peeraddr */
951
952/*
953 * Send data to socket
954 */
955
956int
957ng_btsocket_rfcomm_send(struct socket *so, int flags, struct mbuf *m,
958 struct sockaddr *nam, struct mbuf *control, struct thread *td)
959{
961 int error = 0;
962
963 /* Check socket and input */
964 if (pcb == NULL || m == NULL || control != NULL) {
965 error = EINVAL;
966 goto drop;
967 }
968
969 mtx_lock(&pcb->pcb_mtx);
970
971 /* Make sure DLC is connected */
973 mtx_unlock(&pcb->pcb_mtx);
974 error = ENOTCONN;
975 goto drop;
976 }
977
978 /* Put the packet on the socket's send queue and wakeup RFCOMM task */
979 sbappend(&pcb->so->so_snd, m, flags);
980 m = NULL;
981
985 }
986
987 mtx_unlock(&pcb->pcb_mtx);
988drop:
989 NG_FREE_M(m); /* checks for != NULL */
991
992 return (error);
993} /* ng_btsocket_rfcomm_send */
994
995/*
996 * Get socket address
997 */
998
999int
1000ng_btsocket_rfcomm_sockaddr(struct socket *so, struct sockaddr **nam)
1001{
1003 struct sockaddr_rfcomm sa;
1004
1005 if (pcb == NULL)
1006 return (EINVAL);
1007
1008 bcopy(&pcb->src, &sa.rfcomm_bdaddr, sizeof(sa.rfcomm_bdaddr));
1009 sa.rfcomm_channel = pcb->channel;
1010 sa.rfcomm_len = sizeof(sa);
1011 sa.rfcomm_family = AF_BLUETOOTH;
1012
1013 *nam = sodupsockaddr((struct sockaddr *) &sa, M_NOWAIT);
1014
1015 return ((*nam == NULL)? ENOMEM : 0);
1016} /* ng_btsocket_rfcomm_sockaddr */
1017
1018/*
1019 * Upcall function for L2CAP sockets. Enqueue RFCOMM task.
1020 */
1021
1022static int
1023ng_btsocket_rfcomm_upcall(struct socket *so, void *arg, int waitflag)
1024{
1025 int error;
1026
1027 if (so == NULL)
1028 panic("%s: so == NULL\n", __func__);
1029
1030 if ((error = ng_btsocket_rfcomm_task_wakeup()) != 0)
1032"%s: Could not enqueue RFCOMM task, error=%d\n", __func__, error);
1033 return (SU_OK);
1034} /* ng_btsocket_rfcomm_upcall */
1035
1036/*
1037 * RFCOMM task. Will handle all RFCOMM sessions in one pass.
1038 * XXX FIXME does not scale very well
1039 */
1040
1041static void
1043{
1044 ng_btsocket_rfcomm_session_p s = NULL, s_next = NULL;
1045
1046 mtx_lock(&ng_btsocket_rfcomm_sessions_mtx);
1047
1048 for (s = LIST_FIRST(&ng_btsocket_rfcomm_sessions); s != NULL; ) {
1049 mtx_lock(&s->session_mtx);
1050 s_next = LIST_NEXT(s, next);
1051
1053
1055 /* Unlink and clean the session */
1056 LIST_REMOVE(s, next);
1057
1059 if (!LIST_EMPTY(&s->dlcs))
1060 panic("%s: DLC list is not empty\n", __func__);
1061
1062 /* Close L2CAP socket */
1063 SOCKBUF_LOCK(&s->l2so->so_rcv);
1064 soupcall_clear(s->l2so, SO_RCV);
1065 SOCKBUF_UNLOCK(&s->l2so->so_rcv);
1066 SOCKBUF_LOCK(&s->l2so->so_snd);
1067 soupcall_clear(s->l2so, SO_SND);
1068 SOCKBUF_UNLOCK(&s->l2so->so_snd);
1069 soclose(s->l2so);
1070
1071 mtx_unlock(&s->session_mtx);
1072
1073 mtx_destroy(&s->session_mtx);
1074 bzero(s, sizeof(*s));
1076 } else
1077 mtx_unlock(&s->session_mtx);
1078
1079 s = s_next;
1080 }
1081
1082 mtx_unlock(&ng_btsocket_rfcomm_sessions_mtx);
1083} /* ng_btsocket_rfcomm_sessions_task */
1084
1085/*
1086 * Process RFCOMM session. Will handle all RFCOMM sockets in one pass.
1087 */
1088
1089static void
1091{
1092 mtx_assert(&s->session_mtx, MA_OWNED);
1093
1094 if (s->l2so->so_rcv.sb_state & SBS_CANTRCVMORE) {
1096"%s: L2CAP connection has been terminated, so=%p, so_state=%#x, so_count=%d, " \
1097"state=%d, flags=%#x\n", __func__, s->l2so, s->l2so->so_state,
1098 s->l2so->so_count, s->state, s->flags);
1099
1102 }
1103
1104 /* Now process upcall */
1105 switch (s->state) {
1106 /* Try to accept new L2CAP connection(s) */
1108 while (ng_btsocket_rfcomm_session_accept(s) == 0)
1109 ;
1110 break;
1111
1112 /* Process the results of the L2CAP connect */
1115
1119 }
1120 break;
1121
1122 /* Try to receive/send more data */
1127
1131 } else if (ng_btsocket_rfcomm_session_send(s) != 0) {
1134 }
1135 break;
1136
1138 break;
1139
1140 default:
1141 panic("%s: Invalid session state=%d, flags=%#x\n",
1142 __func__, s->state, s->flags);
1143 break;
1144 }
1145} /* ng_btsocket_rfcomm_session_task */
1146
1147/*
1148 * Process RFCOMM connection indicator. Caller must hold s->session_mtx
1149 */
1150
1153{
1154 ng_btsocket_rfcomm_pcb_p pcb = NULL, pcb1 = NULL;
1155 ng_btsocket_l2cap_pcb_p l2pcb = NULL;
1156 struct socket *so1;
1157
1158 mtx_assert(&s->session_mtx, MA_OWNED);
1159
1160 /*
1161 * Try to find RFCOMM socket that listens on given source address
1162 * and channel. This will return the best possible match.
1163 */
1164
1165 l2pcb = so2l2cap_pcb(s->l2so);
1166 pcb = ng_btsocket_rfcomm_pcb_listener(&l2pcb->src, channel);
1167 if (pcb == NULL)
1168 return (NULL);
1169
1170 /*
1171 * Check the pending connections queue and if we have space then
1172 * create new socket and set proper source and destination address,
1173 * and channel.
1174 */
1175
1176 mtx_lock(&pcb->pcb_mtx);
1177
1178 CURVNET_SET(pcb->so->so_vnet);
1179 so1 = sonewconn(pcb->so, 0);
1180 CURVNET_RESTORE();
1181
1182 mtx_unlock(&pcb->pcb_mtx);
1183
1184 if (so1 == NULL)
1185 return (NULL);
1186
1187 /*
1188 * If we got here than we have created new socket. So complete the
1189 * connection. Set source and destination address from the session.
1190 */
1191
1192 pcb1 = so2rfcomm_pcb(so1);
1193 if (pcb1 == NULL)
1194 panic("%s: pcb1 == NULL\n", __func__);
1195
1196 mtx_lock(&pcb1->pcb_mtx);
1197
1198 bcopy(&l2pcb->src, &pcb1->src, sizeof(pcb1->src));
1199 bcopy(&l2pcb->dst, &pcb1->dst, sizeof(pcb1->dst));
1200 pcb1->channel = channel;
1201
1202 /* Link new DLC to the session. We already hold s->session_mtx */
1203 LIST_INSERT_HEAD(&s->dlcs, pcb1, session_next);
1204 pcb1->session = s;
1205
1206 mtx_unlock(&pcb1->pcb_mtx);
1207
1208 return (pcb1);
1209} /* ng_btsocket_rfcomm_connect_ind */
1210
1211/*
1212 * Process RFCOMM connect confirmation. Caller must hold s->session_mtx.
1213 */
1214
1215static void
1217{
1218 ng_btsocket_rfcomm_pcb_p pcb = NULL, pcb_next = NULL;
1219 int error;
1220
1221 mtx_assert(&s->session_mtx, MA_OWNED);
1222
1223 /*
1224 * Wake up all waiting sockets and send PN request for each of them.
1225 * Note that timeout already been set in ng_btsocket_rfcomm_connect()
1226 *
1227 * Note: cannot use LIST_FOREACH because ng_btsocket_rfcomm_pcb_kill
1228 * will unlink DLC from the session
1229 */
1230
1231 for (pcb = LIST_FIRST(&s->dlcs); pcb != NULL; ) {
1232 mtx_lock(&pcb->pcb_mtx);
1233 pcb_next = LIST_NEXT(pcb, session_next);
1234
1236 pcb->mtu = s->mtu;
1237 bcopy(&so2l2cap_pcb(s->l2so)->src, &pcb->src,
1238 sizeof(pcb->src));
1239
1240 error = ng_btsocket_rfcomm_send_pn(pcb);
1241 if (error == 0)
1243 else
1244 ng_btsocket_rfcomm_pcb_kill(pcb, error);
1245 }
1246
1247 mtx_unlock(&pcb->pcb_mtx);
1248 pcb = pcb_next;
1249 }
1250} /* ng_btsocket_rfcomm_connect_cfm */
1251
1252/*****************************************************************************
1253 *****************************************************************************
1254 ** RFCOMM sessions
1255 *****************************************************************************
1256 *****************************************************************************/
1257
1258/*
1259 * Create new RFCOMM session. That function WILL NOT take ownership over l2so.
1260 * Caller MUST free l2so if function failed.
1261 */
1262
1263static int
1265 struct socket *l2so, bdaddr_p src, bdaddr_p dst,
1266 struct thread *td)
1267{
1269 struct sockaddr_l2cap l2sa;
1270 struct sockopt l2sopt;
1271 int error;
1272 u_int16_t mtu;
1273
1274 mtx_assert(&ng_btsocket_rfcomm_sessions_mtx, MA_OWNED);
1275
1276 /* Allocate the RFCOMM session */
1277 s = malloc(sizeof(*s),
1278 M_NETGRAPH_BTSOCKET_RFCOMM, M_NOWAIT | M_ZERO);
1279 if (s == NULL)
1280 return (ENOMEM);
1281
1282 /* Set defaults */
1284 s->flags = 0;
1287
1288 /*
1289 * XXX Mark session mutex as DUPOK to prevent "duplicated lock of
1290 * the same type" message. When accepting new L2CAP connection
1291 * ng_btsocket_rfcomm_session_accept() holds both session mutexes
1292 * for "old" (accepting) session and "new" (created) session.
1293 */
1294
1295 mtx_init(&s->session_mtx, "btsocks_rfcomm_session_mtx", NULL,
1296 MTX_DEF|MTX_DUPOK);
1297
1298 LIST_INIT(&s->dlcs);
1299
1300 /* Prepare L2CAP socket */
1301 SOCKBUF_LOCK(&l2so->so_rcv);
1302 soupcall_set(l2so, SO_RCV, ng_btsocket_rfcomm_upcall, NULL);
1303 SOCKBUF_UNLOCK(&l2so->so_rcv);
1304 SOCKBUF_LOCK(&l2so->so_snd);
1305 soupcall_set(l2so, SO_SND, ng_btsocket_rfcomm_upcall, NULL);
1306 SOCKBUF_UNLOCK(&l2so->so_snd);
1307 l2so->so_state |= SS_NBIO;
1308 s->l2so = l2so;
1309
1310 mtx_lock(&s->session_mtx);
1311
1312 /*
1313 * "src" == NULL and "dst" == NULL means just create session.
1314 * caller must do the rest
1315 */
1316
1317 if (src == NULL && dst == NULL)
1318 goto done;
1319
1320 /*
1321 * Set incoming MTU on L2CAP socket. It is RFCOMM session default MTU
1322 * plus 5 bytes: RFCOMM frame header, one extra byte for length and one
1323 * extra byte for credits.
1324 */
1325
1326 mtu = s->mtu + sizeof(struct rfcomm_frame_hdr) + 1 + 1;
1327
1328 l2sopt.sopt_dir = SOPT_SET;
1329 l2sopt.sopt_level = SOL_L2CAP;
1330 l2sopt.sopt_name = SO_L2CAP_IMTU;
1331 l2sopt.sopt_val = (void *) &mtu;
1332 l2sopt.sopt_valsize = sizeof(mtu);
1333 l2sopt.sopt_td = NULL;
1334
1335 error = sosetopt(s->l2so, &l2sopt);
1336 if (error != 0)
1337 goto bad;
1338
1339 /* Bind socket to "src" address */
1340 l2sa.l2cap_len = sizeof(l2sa);
1341 l2sa.l2cap_family = AF_BLUETOOTH;
1342 l2sa.l2cap_psm = (dst == NULL)? htole16(NG_L2CAP_PSM_RFCOMM) : 0;
1343 bcopy(src, &l2sa.l2cap_bdaddr, sizeof(l2sa.l2cap_bdaddr));
1344 l2sa.l2cap_cid = 0;
1346
1347 error = sobind(s->l2so, (struct sockaddr *) &l2sa, td);
1348 if (error != 0)
1349 goto bad;
1350
1351 /* If "dst" is not NULL then initiate connect(), otherwise listen() */
1352 if (dst == NULL) {
1353 s->flags = 0;
1355
1356 error = solisten(s->l2so, 10, td);
1357 if (error != 0)
1358 goto bad;
1359 } else {
1362
1363 l2sa.l2cap_len = sizeof(l2sa);
1364 l2sa.l2cap_family = AF_BLUETOOTH;
1365 l2sa.l2cap_psm = htole16(NG_L2CAP_PSM_RFCOMM);
1366 bcopy(dst, &l2sa.l2cap_bdaddr, sizeof(l2sa.l2cap_bdaddr));
1367 l2sa.l2cap_cid = 0;
1369
1370 error = soconnect(s->l2so, (struct sockaddr *) &l2sa, td);
1371 if (error != 0)
1372 goto bad;
1373 }
1374
1375done:
1376 LIST_INSERT_HEAD(&ng_btsocket_rfcomm_sessions, s, next);
1377 *sp = s;
1378
1379 mtx_unlock(&s->session_mtx);
1380
1381 return (0);
1382
1383bad:
1384 mtx_unlock(&s->session_mtx);
1385
1386 /* Return L2CAP socket back to its original state */
1387 SOCKBUF_LOCK(&l2so->so_rcv);
1388 soupcall_clear(s->l2so, SO_RCV);
1389 SOCKBUF_UNLOCK(&l2so->so_rcv);
1390 SOCKBUF_LOCK(&l2so->so_snd);
1391 soupcall_clear(s->l2so, SO_SND);
1392 SOCKBUF_UNLOCK(&l2so->so_snd);
1393 l2so->so_state &= ~SS_NBIO;
1394
1395 mtx_destroy(&s->session_mtx);
1396 bzero(s, sizeof(*s));
1398
1399 return (error);
1400} /* ng_btsocket_rfcomm_session_create */
1401
1402/*
1403 * Process accept() on RFCOMM session
1404 * XXX FIXME locking for "l2so"?
1405 */
1406
1407static int
1409{
1410 struct socket *l2so;
1411 struct sockaddr_l2cap *l2sa = NULL;
1412 ng_btsocket_l2cap_pcb_t *l2pcb = NULL;
1414 int error;
1415
1416 mtx_assert(&ng_btsocket_rfcomm_sessions_mtx, MA_OWNED);
1417 mtx_assert(&s0->session_mtx, MA_OWNED);
1418
1419 SOLISTEN_LOCK(s0->l2so);
1420 error = solisten_dequeue(s0->l2so, &l2so, 0);
1421 if (error == EWOULDBLOCK)
1422 return (error);
1423 if (error) {
1425"%s: Could not accept connection on L2CAP socket, error=%d\n", __func__, error);
1426 return (error);
1427 }
1428
1429 error = soaccept(l2so, (struct sockaddr **) &l2sa);
1430 if (error != 0) {
1432"%s: soaccept() on L2CAP socket failed, error=%d\n", __func__, error);
1433 soclose(l2so);
1434
1435 return (error);
1436 }
1437
1438 /*
1439 * Check if there is already active RFCOMM session between two devices.
1440 * If so then close L2CAP connection. We only support one RFCOMM session
1441 * between each pair of devices. Note that here we assume session in any
1442 * state. The session even could be in the middle of disconnecting.
1443 */
1444
1445 l2pcb = so2l2cap_pcb(l2so);
1446 s = ng_btsocket_rfcomm_session_by_addr(&l2pcb->src, &l2pcb->dst);
1447 if (s == NULL) {
1448 /* Create a new RFCOMM session */
1449 error = ng_btsocket_rfcomm_session_create(&s, l2so, NULL, NULL,
1450 curthread /* XXX */);
1451 if (error == 0) {
1452 mtx_lock(&s->session_mtx);
1453
1454 s->flags = 0;
1456
1457 /*
1458 * Adjust MTU on incoming connection. Reserve 5 bytes:
1459 * RFCOMM frame header, one extra byte for length and
1460 * one extra byte for credits.
1461 */
1462
1463 s->mtu = min(l2pcb->imtu, l2pcb->omtu) -
1464 sizeof(struct rfcomm_frame_hdr) - 1 - 1;
1465
1466 mtx_unlock(&s->session_mtx);
1467 } else {
1469"%s: Failed to create new RFCOMM session, error=%d\n", __func__, error);
1470
1471 soclose(l2so);
1472 }
1473 } else {
1475"%s: Rejecting duplicating RFCOMM session between src=%x:%x:%x:%x:%x:%x and " \
1476"dst=%x:%x:%x:%x:%x:%x, state=%d, flags=%#x\n", __func__,
1477 l2pcb->src.b[5], l2pcb->src.b[4], l2pcb->src.b[3],
1478 l2pcb->src.b[2], l2pcb->src.b[1], l2pcb->src.b[0],
1479 l2pcb->dst.b[5], l2pcb->dst.b[4], l2pcb->dst.b[3],
1480 l2pcb->dst.b[2], l2pcb->dst.b[1], l2pcb->dst.b[0],
1481 s->state, s->flags);
1482
1483 error = EBUSY;
1484 soclose(l2so);
1485 }
1486
1487 return (error);
1488} /* ng_btsocket_rfcomm_session_accept */
1489
1490/*
1491 * Process connect() on RFCOMM session
1492 * XXX FIXME locking for "l2so"?
1493 */
1494
1495static int
1497{
1499 int error;
1500
1501 mtx_assert(&s->session_mtx, MA_OWNED);
1502
1503 /* First check if connection has failed */
1504 if ((error = s->l2so->so_error) != 0) {
1505 s->l2so->so_error = 0;
1506
1508"%s: Could not connect RFCOMM session, error=%d, state=%d, flags=%#x\n",
1509 __func__, error, s->state, s->flags);
1510
1511 return (error);
1512 }
1513
1514 /* Is connection still in progress? */
1515 if (s->l2so->so_state & SS_ISCONNECTING)
1516 return (0);
1517
1518 /*
1519 * If we got here then we are connected. Send SABM on DLCI 0 to
1520 * open multiplexor channel.
1521 */
1522
1523 if (error == 0) {
1525
1526 /*
1527 * Adjust MTU on outgoing connection. Reserve 5 bytes: RFCOMM
1528 * frame header, one extra byte for length and one extra byte
1529 * for credits.
1530 */
1531
1532 s->mtu = min(l2pcb->imtu, l2pcb->omtu) -
1533 sizeof(struct rfcomm_frame_hdr) - 1 - 1;
1534
1536 if (error == 0)
1538 }
1539
1540 return (error);
1541}/* ng_btsocket_rfcomm_session_connect */
1542
1543/*
1544 * Receive data on RFCOMM session
1545 * XXX FIXME locking for "l2so"?
1546 */
1547
1548static int
1550{
1551 struct mbuf *m = NULL;
1552 struct uio uio;
1553 int more, flags, error;
1554
1555 mtx_assert(&s->session_mtx, MA_OWNED);
1556
1557 /* Can we read from the L2CAP socket? */
1558 if (!soreadable(s->l2so))
1559 return (0);
1560
1561 /* First check for error on L2CAP socket */
1562 if ((error = s->l2so->so_error) != 0) {
1563 s->l2so->so_error = 0;
1564
1566"%s: Could not receive data from L2CAP socket, error=%d, state=%d, flags=%#x\n",
1567 __func__, error, s->state, s->flags);
1568
1569 return (error);
1570 }
1571
1572 /*
1573 * Read all packets from the L2CAP socket.
1574 * XXX FIXME/VERIFY is that correct? For now use m->m_nextpkt as
1575 * indication that there is more packets on the socket's buffer.
1576 * Also what should we use in uio.uio_resid?
1577 * May be s->mtu + sizeof(struct rfcomm_frame_hdr) + 1 + 1?
1578 */
1579
1580 for (more = 1; more; ) {
1581 /* Try to get next packet from socket */
1582 bzero(&uio, sizeof(uio));
1583/* uio.uio_td = NULL; */
1584 uio.uio_resid = 1000000000;
1585 flags = MSG_DONTWAIT;
1586
1587 m = NULL;
1588 error = soreceive(s->l2so, NULL, &uio, &m,
1589 (struct mbuf **) NULL, &flags);
1590 if (error != 0) {
1591 if (error == EWOULDBLOCK)
1592 return (0); /* XXX can happen? */
1593
1595"%s: Could not receive data from L2CAP socket, error=%d\n", __func__, error);
1596
1597 return (error);
1598 }
1599
1600 more = (m->m_nextpkt != NULL);
1601 m->m_nextpkt = NULL;
1602
1604 }
1605
1606 return (0);
1607} /* ng_btsocket_rfcomm_session_receive */
1608
1609/*
1610 * Send data on RFCOMM session
1611 * XXX FIXME locking for "l2so"?
1612 */
1613
1614static int
1616{
1617 struct mbuf *m = NULL;
1618 int error;
1619
1620 mtx_assert(&s->session_mtx, MA_OWNED);
1621
1622 /* Send as much as we can from the session queue */
1623 while (sowriteable(s->l2so)) {
1624 /* Check if socket still OK */
1625 if ((error = s->l2so->so_error) != 0) {
1626 s->l2so->so_error = 0;
1627
1629"%s: Detected error=%d on L2CAP socket, state=%d, flags=%#x\n",
1630 __func__, error, s->state, s->flags);
1631
1632 return (error);
1633 }
1634
1635 NG_BT_MBUFQ_DEQUEUE(&s->outq, m);
1636 if (m == NULL)
1637 return (0); /* we are done */
1638
1639 /* Call send function on the L2CAP socket */
1640 error = (*s->l2so->so_proto->pr_usrreqs->pru_send)(s->l2so,
1641 0, m, NULL, NULL, curthread /* XXX */);
1642 if (error != 0) {
1644"%s: Could not send data to L2CAP socket, error=%d\n", __func__, error);
1645
1646 return (error);
1647 }
1648 }
1649
1650 return (0);
1651} /* ng_btsocket_rfcomm_session_send */
1652
1653/*
1654 * Close and disconnect all DLCs for the given session. Caller must hold
1655 * s->sesson_mtx. Will wakeup session.
1656 */
1657
1658static void
1660{
1661 ng_btsocket_rfcomm_pcb_p pcb = NULL, pcb_next = NULL;
1662 int error;
1663
1664 mtx_assert(&s->session_mtx, MA_OWNED);
1665
1666 /*
1667 * Note: cannot use LIST_FOREACH because ng_btsocket_rfcomm_pcb_kill
1668 * will unlink DLC from the session
1669 */
1670
1671 for (pcb = LIST_FIRST(&s->dlcs); pcb != NULL; ) {
1672 mtx_lock(&pcb->pcb_mtx);
1673 pcb_next = LIST_NEXT(pcb, session_next);
1674
1676"%s: Disconnecting dlci=%d, state=%d, flags=%#x\n",
1677 __func__, pcb->dlci, pcb->state, pcb->flags);
1678
1680 error = ECONNRESET;
1681 else
1682 error = ECONNREFUSED;
1683
1684 ng_btsocket_rfcomm_pcb_kill(pcb, error);
1685
1686 mtx_unlock(&pcb->pcb_mtx);
1687 pcb = pcb_next;
1688 }
1689} /* ng_btsocket_rfcomm_session_clean */
1690
1691/*
1692 * Process all DLCs on the session. Caller MUST hold s->session_mtx.
1693 */
1694
1695static void
1697{
1698 ng_btsocket_rfcomm_pcb_p pcb = NULL, pcb_next = NULL;
1699 int error;
1700
1701 mtx_assert(&s->session_mtx, MA_OWNED);
1702
1703 /*
1704 * Note: cannot use LIST_FOREACH because ng_btsocket_rfcomm_pcb_kill
1705 * will unlink DLC from the session
1706 */
1707
1708 for (pcb = LIST_FIRST(&s->dlcs); pcb != NULL; ) {
1709 mtx_lock(&pcb->pcb_mtx);
1710 pcb_next = LIST_NEXT(pcb, session_next);
1711
1712 switch (pcb->state) {
1713 /*
1714 * If DLC in W4_CONNECT state then we should check for both
1715 * timeout and detach.
1716 */
1717
1721 else if (pcb->flags & NG_BTSOCKET_RFCOMM_DLC_TIMEDOUT)
1722 ng_btsocket_rfcomm_pcb_kill(pcb, ETIMEDOUT);
1723 break;
1724
1725 /*
1726 * If DLC in CONFIGURING or CONNECTING state then we only
1727 * should check for timeout. If detach() was called then
1728 * DLC will be moved into DISCONNECTING state.
1729 */
1730
1734 ng_btsocket_rfcomm_pcb_kill(pcb, ETIMEDOUT);
1735 break;
1736
1737 /*
1738 * If DLC in CONNECTED state then we need to send data (if any)
1739 * from the socket's send queue. Note that we will send data
1740 * from either all sockets or none. This may overload session's
1741 * outgoing queue (but we do not check for that).
1742 *
1743 * XXX FIXME need scheduler for RFCOMM sockets
1744 */
1745
1747 error = ng_btsocket_rfcomm_pcb_send(pcb, ALOT);
1748 if (error != 0)
1749 ng_btsocket_rfcomm_pcb_kill(pcb, error);
1750 break;
1751
1752 /*
1753 * If DLC in DISCONNECTING state then we must send DISC frame.
1754 * Note that if DLC has timeout set then we do not need to
1755 * resend DISC frame.
1756 *
1757 * XXX FIXME need to drain all data from the socket's queue
1758 * if LINGER option was set
1759 */
1760
1762 if (!(pcb->flags & NG_BTSOCKET_RFCOMM_DLC_TIMO)) {
1765 pcb->dlci);
1766 if (error == 0)
1768 else
1769 ng_btsocket_rfcomm_pcb_kill(pcb, error);
1770 } else if (pcb->flags & NG_BTSOCKET_RFCOMM_DLC_TIMEDOUT)
1771 ng_btsocket_rfcomm_pcb_kill(pcb, ETIMEDOUT);
1772 break;
1773
1774/* case NG_BTSOCKET_RFCOMM_DLC_CLOSED: */
1775 default:
1776 panic("%s: Invalid DLC state=%d, flags=%#x\n",
1777 __func__, pcb->state, pcb->flags);
1778 break;
1779 }
1780
1781 mtx_unlock(&pcb->pcb_mtx);
1782 pcb = pcb_next;
1783 }
1784} /* ng_btsocket_rfcomm_session_process_pcb */
1785
1786/*
1787 * Find RFCOMM session between "src" and "dst".
1788 * Caller MUST hold ng_btsocket_rfcomm_sessions_mtx.
1789 */
1790
1793{
1795 ng_btsocket_l2cap_pcb_p l2pcb = NULL;
1796 int any_src;
1797
1798 mtx_assert(&ng_btsocket_rfcomm_sessions_mtx, MA_OWNED);
1799
1800 any_src = (bcmp(src, NG_HCI_BDADDR_ANY, sizeof(*src)) == 0);
1801
1802 LIST_FOREACH(s, &ng_btsocket_rfcomm_sessions, next) {
1803 l2pcb = so2l2cap_pcb(s->l2so);
1804
1805 if ((any_src || bcmp(&l2pcb->src, src, sizeof(*src)) == 0) &&
1806 bcmp(&l2pcb->dst, dst, sizeof(*dst)) == 0)
1807 break;
1808 }
1809
1810 return (s);
1811} /* ng_btsocket_rfcomm_session_by_addr */
1812
1813/*****************************************************************************
1814 *****************************************************************************
1815 ** RFCOMM
1816 *****************************************************************************
1817 *****************************************************************************/
1818
1819/*
1820 * Process incoming RFCOMM frame. Caller must hold s->session_mtx.
1821 * XXX FIXME check frame length
1822 */
1823
1824static int
1826 struct mbuf *m0)
1827{
1828 struct rfcomm_frame_hdr *hdr = NULL;
1829 struct mbuf *m = NULL;
1830 u_int16_t length;
1831 u_int8_t dlci, type;
1832 int error = 0;
1833
1834 mtx_assert(&s->session_mtx, MA_OWNED);
1835
1836 /* Pullup as much as we can into first mbuf (for direct access) */
1837 length = min(m0->m_pkthdr.len, MHLEN);
1838 if (m0->m_len < length) {
1839 if ((m0 = m_pullup(m0, length)) == NULL) {
1841"%s: m_pullup(%d) failed\n", __func__, length);
1842
1843 return (ENOBUFS);
1844 }
1845 }
1846
1847 hdr = mtod(m0, struct rfcomm_frame_hdr *);
1848 dlci = RFCOMM_DLCI(hdr->address);
1849 type = RFCOMM_TYPE(hdr->control);
1850
1851 /* Test EA bit in length. If not set then we have 2 bytes of length */
1852 if (!RFCOMM_EA(hdr->length)) {
1853 bcopy(&hdr->length, &length, sizeof(length));
1854 length = le16toh(length) >> 1;
1855 m_adj(m0, sizeof(*hdr) + 1);
1856 } else {
1857 length = hdr->length >> 1;
1858 m_adj(m0, sizeof(*hdr));
1859 }
1860
1862"%s: Got frame type=%#x, dlci=%d, length=%d, cr=%d, pf=%d, len=%d\n",
1863 __func__, type, dlci, length, RFCOMM_CR(hdr->address),
1864 RFCOMM_PF(hdr->control), m0->m_pkthdr.len);
1865
1866 /*
1867 * Get FCS (the last byte in the frame)
1868 * XXX this will not work if mbuf chain ends with empty mbuf.
1869 * XXX let's hope it never happens :)
1870 */
1871
1872 for (m = m0; m->m_next != NULL; m = m->m_next)
1873 ;
1874 if (m->m_len <= 0)
1875 panic("%s: Empty mbuf at the end of the chain, len=%d\n",
1876 __func__, m->m_len);
1877
1878 /*
1879 * Check FCS. We only need to calculate FCS on first 2 or 3 bytes
1880 * and already m_pullup'ed mbuf chain, so it should be safe.
1881 */
1882
1883 if (ng_btsocket_rfcomm_check_fcs((u_int8_t *) hdr, type, m->m_data[m->m_len - 1])) {
1885"%s: Invalid RFCOMM packet. Bad checksum\n", __func__);
1886 NG_FREE_M(m0);
1887
1888 return (EINVAL);
1889 }
1890
1891 m_adj(m0, -1); /* Trim FCS byte */
1892
1893 /*
1894 * Process RFCOMM frame.
1895 *
1896 * From TS 07.10 spec
1897 *
1898 * "... In the case where a SABM or DISC command with the P bit set
1899 * to 0 is received then the received frame shall be discarded..."
1900 *
1901 * "... If a unsolicited DM response is received then the frame shall
1902 * be processed irrespective of the P/F setting... "
1903 *
1904 * "... The station may transmit response frames with the F bit set
1905 * to 0 at any opportunity on an asynchronous basis. However, in the
1906 * case where a UA response is received with the F bit set to 0 then
1907 * the received frame shall be discarded..."
1908 *
1909 * From Bluetooth spec
1910 *
1911 * "... When credit based flow control is being used, the meaning of
1912 * the P/F bit in the control field of the RFCOMM header is redefined
1913 * for UIH frames..."
1914 */
1915
1916 switch (type) {
1917 case RFCOMM_FRAME_SABM:
1918 if (RFCOMM_PF(hdr->control))
1920 break;
1921
1922 case RFCOMM_FRAME_DISC:
1923 if (RFCOMM_PF(hdr->control))
1925 break;
1926
1927 case RFCOMM_FRAME_UA:
1928 if (RFCOMM_PF(hdr->control))
1930 break;
1931
1932 case RFCOMM_FRAME_DM:
1934 break;
1935
1936 case RFCOMM_FRAME_UIH:
1937 if (dlci == 0)
1938 error = ng_btsocket_rfcomm_receive_mcc(s, m0);
1939 else
1941 RFCOMM_PF(hdr->control), m0);
1942
1943 return (error);
1944 /* NOT REACHED */
1945
1946 default:
1948"%s: Invalid RFCOMM packet. Unknown type=%#x\n", __func__, type);
1949 error = EINVAL;
1950 break;
1951 }
1952
1953 NG_FREE_M(m0);
1954
1955 return (error);
1956} /* ng_btsocket_rfcomm_receive_frame */
1957
1958/*
1959 * Process RFCOMM SABM frame
1960 */
1961
1962static int
1964{
1965 ng_btsocket_rfcomm_pcb_p pcb = NULL;
1966 int error = 0;
1967
1968 mtx_assert(&s->session_mtx, MA_OWNED);
1969
1971"%s: Got SABM, session state=%d, flags=%#x, mtu=%d, dlci=%d\n",
1972 __func__, s->state, s->flags, s->mtu, dlci);
1973
1974 /* DLCI == 0 means open multiplexor channel */
1975 if (dlci == 0) {
1976 switch (s->state) {
1981 if (error == 0) {
1984 } else {
1987 }
1988 break;
1989
1990 default:
1992"%s: Got SABM for session in invalid state state=%d, flags=%#x\n",
1993 __func__, s->state, s->flags);
1994 error = EINVAL;
1995 break;
1996 }
1997
1998 return (error);
1999 }
2000
2001 /* Make sure multiplexor channel is open */
2004"%s: Got SABM for dlci=%d with mulitplexor channel closed, state=%d, " \
2005"flags=%#x\n", __func__, dlci, s->state, s->flags);
2006
2007 return (EINVAL);
2008 }
2009
2010 /*
2011 * Check if we have this DLCI. This might happen when remote
2012 * peer uses PN command before actual open (SABM) happens.
2013 */
2014
2016 if (pcb != NULL) {
2017 mtx_lock(&pcb->pcb_mtx);
2018
2021"%s: Got SABM for dlci=%d in invalid state=%d, flags=%#x\n",
2022 __func__, dlci, pcb->state, pcb->flags);
2023 mtx_unlock(&pcb->pcb_mtx);
2024
2025 return (ENOENT);
2026 }
2027
2029
2031 if (error == 0)
2032 error = ng_btsocket_rfcomm_send_msc(pcb);
2033
2034 if (error == 0) {
2036 soisconnected(pcb->so);
2037 } else
2038 ng_btsocket_rfcomm_pcb_kill(pcb, error);
2039
2040 mtx_unlock(&pcb->pcb_mtx);
2041
2042 return (error);
2043 }
2044
2045 /*
2046 * We do not have requested DLCI, so it must be an incoming connection
2047 * with default parameters. Try to accept it.
2048 */
2049
2051 if (pcb != NULL) {
2052 mtx_lock(&pcb->pcb_mtx);
2053
2054 pcb->dlci = dlci;
2055
2057 if (error == 0)
2058 error = ng_btsocket_rfcomm_send_msc(pcb);
2059
2060 if (error == 0) {
2062 soisconnected(pcb->so);
2063 } else
2064 ng_btsocket_rfcomm_pcb_kill(pcb, error);
2065
2066 mtx_unlock(&pcb->pcb_mtx);
2067 } else
2068 /* Nobody is listen()ing on the requested DLCI */
2070
2071 return (error);
2072} /* ng_btsocket_rfcomm_receive_sabm */
2073
2074/*
2075 * Process RFCOMM DISC frame
2076 */
2077
2078static int
2080{
2081 ng_btsocket_rfcomm_pcb_p pcb = NULL;
2082 int error = 0;
2083
2084 mtx_assert(&s->session_mtx, MA_OWNED);
2085
2087"%s: Got DISC, session state=%d, flags=%#x, mtu=%d, dlci=%d\n",
2088 __func__, s->state, s->flags, s->mtu, dlci);
2089
2090 /* DLCI == 0 means close multiplexor channel */
2091 if (dlci == 0) {
2092 /* XXX FIXME assume that remote side will close the socket */
2094 if (error == 0) {
2097 else
2099 } else
2101
2103 } else {
2105 if (pcb != NULL) {
2106 int err;
2107
2108 mtx_lock(&pcb->pcb_mtx);
2109
2111"%s: Got DISC for dlci=%d, state=%d, flags=%#x\n",
2112 __func__, dlci, pcb->state, pcb->flags);
2113
2116
2118 err = 0;
2119 else
2120 err = ECONNREFUSED;
2121
2123
2124 mtx_unlock(&pcb->pcb_mtx);
2125 } else {
2127"%s: Got DISC for non-existing dlci=%d\n", __func__, dlci);
2128
2131 }
2132 }
2133
2134 return (error);
2135} /* ng_btsocket_rfcomm_receive_disc */
2136
2137/*
2138 * Process RFCOMM UA frame
2139 */
2140
2141static int
2143{
2144 ng_btsocket_rfcomm_pcb_p pcb = NULL;
2145 int error = 0;
2146
2147 mtx_assert(&s->session_mtx, MA_OWNED);
2148
2150"%s: Got UA, session state=%d, flags=%#x, mtu=%d, dlci=%d\n",
2151 __func__, s->state, s->flags, s->mtu, dlci);
2152
2153 /* dlci == 0 means multiplexor channel */
2154 if (dlci == 0) {
2155 switch (s->state) {
2159 break;
2160
2164 break;
2165
2166 default:
2168"%s: Got UA for session in invalid state=%d(%d), flags=%#x, mtu=%d\n",
2169 __func__, s->state, INITIATOR(s), s->flags,
2170 s->mtu);
2171 error = ENOENT;
2172 break;
2173 }
2174
2175 return (error);
2176 }
2177
2178 /* Check if we have this DLCI */
2180 if (pcb != NULL) {
2181 mtx_lock(&pcb->pcb_mtx);
2182
2184"%s: Got UA for dlci=%d, state=%d, flags=%#x\n",
2185 __func__, dlci, pcb->state, pcb->flags);
2186
2187 switch (pcb->state) {
2190
2191 error = ng_btsocket_rfcomm_send_msc(pcb);
2192 if (error == 0) {
2194 soisconnected(pcb->so);
2195 }
2196 break;
2197
2200 break;
2201
2202 default:
2204"%s: Got UA for dlci=%d in invalid state=%d, flags=%#x\n",
2205 __func__, dlci, pcb->state, pcb->flags);
2206 error = ENOENT;
2207 break;
2208 }
2209
2210 mtx_unlock(&pcb->pcb_mtx);
2211 } else {
2213"%s: Got UA for non-existing dlci=%d\n", __func__, dlci);
2214
2216 }
2217
2218 return (error);
2219} /* ng_btsocket_rfcomm_receive_ua */
2220
2221/*
2222 * Process RFCOMM DM frame
2223 */
2224
2225static int
2227{
2228 ng_btsocket_rfcomm_pcb_p pcb = NULL;
2229 int error;
2230
2231 mtx_assert(&s->session_mtx, MA_OWNED);
2232
2234"%s: Got DM, session state=%d, flags=%#x, mtu=%d, dlci=%d\n",
2235 __func__, s->state, s->flags, s->mtu, dlci);
2236
2237 /* DLCI == 0 means multiplexor channel */
2238 if (dlci == 0) {
2239 /* Disconnect all dlc's on the session */
2242 } else {
2244 if (pcb != NULL) {
2245 mtx_lock(&pcb->pcb_mtx);
2246
2248"%s: Got DM for dlci=%d, state=%d, flags=%#x\n",
2249 __func__, dlci, pcb->state, pcb->flags);
2250
2252 error = ECONNRESET;
2253 else
2254 error = ECONNREFUSED;
2255
2256 ng_btsocket_rfcomm_pcb_kill(pcb, error);
2257
2258 mtx_unlock(&pcb->pcb_mtx);
2259 } else
2261"%s: Got DM for non-existing dlci=%d\n", __func__, dlci);
2262 }
2263
2264 return (0);
2265} /* ng_btsocket_rfcomm_receive_dm */
2266
2267/*
2268 * Process RFCOMM UIH frame (data)
2269 */
2270
2271static int
2273 int pf, struct mbuf *m0)
2274{
2275 ng_btsocket_rfcomm_pcb_p pcb = NULL;
2276 int error = 0;
2277
2278 mtx_assert(&s->session_mtx, MA_OWNED);
2279
2281"%s: Got UIH, session state=%d, flags=%#x, mtu=%d, dlci=%d, pf=%d, len=%d\n",
2282 __func__, s->state, s->flags, s->mtu, dlci, pf,
2283 m0->m_pkthdr.len);
2284
2285 /* XXX should we do it here? Check for session flow control */
2288"%s: Got UIH with session flow control asserted, state=%d, flags=%#x\n",
2289 __func__, s->state, s->flags);
2290 goto drop;
2291 }
2292
2293 /* Check if we have this dlci */
2295 if (pcb == NULL) {
2297"%s: Got UIH for non-existing dlci=%d\n", __func__, dlci);
2299 goto drop;
2300 }
2301
2302 mtx_lock(&pcb->pcb_mtx);
2303
2304 /* Check dlci state */
2307"%s: Got UIH for dlci=%d in invalid state=%d, flags=%#x\n",
2308 __func__, dlci, pcb->state, pcb->flags);
2309 error = EINVAL;
2310 goto drop1;
2311 }
2312
2313 /* Check dlci flow control */
2314 if (((pcb->flags & NG_BTSOCKET_RFCOMM_DLC_CFC) && pcb->rx_cred <= 0) ||
2315 (pcb->lmodem & RFCOMM_MODEM_FC)) {
2317"%s: Got UIH for dlci=%d with asserted flow control, state=%d, " \
2318"flags=%#x, rx_cred=%d, lmodem=%#x\n",
2319 __func__, dlci, pcb->state, pcb->flags,
2320 pcb->rx_cred, pcb->lmodem);
2321 goto drop1;
2322 }
2323
2324 /* Did we get any credits? */
2325 if ((pcb->flags & NG_BTSOCKET_RFCOMM_DLC_CFC) && pf) {
2327"%s: Got %d more credits for dlci=%d, state=%d, flags=%#x, " \
2328"rx_cred=%d, tx_cred=%d\n",
2329 __func__, *mtod(m0, u_int8_t *), dlci, pcb->state,
2330 pcb->flags, pcb->rx_cred, pcb->tx_cred);
2331
2332 pcb->tx_cred += *mtod(m0, u_int8_t *);
2333 m_adj(m0, 1);
2334
2335 /* Send more from the DLC. XXX check for errors? */
2337 }
2338
2339 /* OK the of the rest of the mbuf is the data */
2340 if (m0->m_pkthdr.len > 0) {
2341 /* If we are using credit flow control decrease rx_cred here */
2342 if (pcb->flags & NG_BTSOCKET_RFCOMM_DLC_CFC) {
2343 /* Give remote peer more credits (if needed) */
2344 if (-- pcb->rx_cred <= RFCOMM_MAX_CREDITS / 2)
2346 else
2348"%s: Remote side still has credits, dlci=%d, state=%d, flags=%#x, " \
2349"rx_cred=%d, tx_cred=%d\n", __func__, dlci, pcb->state, pcb->flags,
2350 pcb->rx_cred, pcb->tx_cred);
2351 }
2352
2353 /* Check packet against mtu on dlci */
2354 if (m0->m_pkthdr.len > pcb->mtu) {
2356"%s: Got oversized UIH for dlci=%d, state=%d, flags=%#x, mtu=%d, len=%d\n",
2357 __func__, dlci, pcb->state, pcb->flags,
2358 pcb->mtu, m0->m_pkthdr.len);
2359
2360 error = EMSGSIZE;
2361 } else if (m0->m_pkthdr.len > sbspace(&pcb->so->so_rcv)) {
2362 /*
2363 * This is really bad. Receive queue on socket does
2364 * not have enough space for the packet. We do not
2365 * have any other choice but drop the packet.
2366 */
2367
2369"%s: Not enough space in socket receive queue. Dropping UIH for dlci=%d, " \
2370"state=%d, flags=%#x, len=%d, space=%ld\n",
2371 __func__, dlci, pcb->state, pcb->flags,
2372 m0->m_pkthdr.len, sbspace(&pcb->so->so_rcv));
2373
2374 error = ENOBUFS;
2375 } else {
2376 /* Append packet to the socket receive queue */
2377 sbappend(&pcb->so->so_rcv, m0, 0);
2378 m0 = NULL;
2379
2380 sorwakeup(pcb->so);
2381 }
2382 }
2383drop1:
2384 mtx_unlock(&pcb->pcb_mtx);
2385drop:
2386 NG_FREE_M(m0); /* checks for != NULL */
2387
2388 return (error);
2389} /* ng_btsocket_rfcomm_receive_uih */
2390
2391/*
2392 * Process RFCOMM MCC command (Multiplexor)
2393 *
2394 * From TS 07.10 spec
2395 *
2396 * "5.4.3.1 Information Data
2397 *
2398 * ...The frames (UIH) sent by the initiating station have the C/R bit set
2399 * to 1 and those sent by the responding station have the C/R bit set to 0..."
2400 *
2401 * "5.4.6.2 Operating procedures
2402 *
2403 * Messages always exist in pairs; a command message and a corresponding
2404 * response message. If the C/R bit is set to 1 the message is a command,
2405 * if it is set to 0 the message is a response...
2406 *
2407 * ...
2408 *
2409 * NOTE: Notice that when UIH frames are used to convey information on DLCI 0
2410 * there are at least two different fields that contain a C/R bit, and the
2411 * bits are set of different form. The C/R bit in the Type field shall be set
2412 * as it is stated above, while the C/R bit in the Address field (see subclause
2413 * 5.2.1.2) shall be set as it is described in subclause 5.4.3.1."
2414 */
2415
2416static int
2418{
2419 struct rfcomm_mcc_hdr *hdr = NULL;
2420 u_int8_t cr, type, length;
2421
2422 mtx_assert(&s->session_mtx, MA_OWNED);
2423
2424 /*
2425 * We can access data directly in the first mbuf, because we have
2426 * m_pullup()'ed mbuf chain in ng_btsocket_rfcomm_receive_frame().
2427 * All MCC commands should fit into single mbuf (except probably TEST).
2428 */
2429
2430 hdr = mtod(m0, struct rfcomm_mcc_hdr *);
2431 cr = RFCOMM_CR(hdr->type);
2432 type = RFCOMM_MCC_TYPE(hdr->type);
2434
2435 /* Check MCC frame length */
2436 if (sizeof(*hdr) + length != m0->m_pkthdr.len) {
2438"%s: Invalid MCC frame length=%d, len=%d\n",
2439 __func__, length, m0->m_pkthdr.len);
2440 NG_FREE_M(m0);
2441
2442 return (EMSGSIZE);
2443 }
2444
2445 switch (type) {
2446 case RFCOMM_MCC_TEST:
2447 return (ng_btsocket_rfcomm_receive_test(s, m0));
2448 /* NOT REACHED */
2449
2450 case RFCOMM_MCC_FCON:
2451 case RFCOMM_MCC_FCOFF:
2452 return (ng_btsocket_rfcomm_receive_fc(s, m0));
2453 /* NOT REACHED */
2454
2455 case RFCOMM_MCC_MSC:
2456 return (ng_btsocket_rfcomm_receive_msc(s, m0));
2457 /* NOT REACHED */
2458
2459 case RFCOMM_MCC_RPN:
2460 return (ng_btsocket_rfcomm_receive_rpn(s, m0));
2461 /* NOT REACHED */
2462
2463 case RFCOMM_MCC_RLS:
2464 return (ng_btsocket_rfcomm_receive_rls(s, m0));
2465 /* NOT REACHED */
2466
2467 case RFCOMM_MCC_PN:
2468 return (ng_btsocket_rfcomm_receive_pn(s, m0));
2469 /* NOT REACHED */
2470
2471 case RFCOMM_MCC_NSC:
2473"%s: Got MCC NSC, type=%#x, cr=%d, length=%d, session state=%d, flags=%#x, " \
2474"mtu=%d, len=%d\n", __func__, RFCOMM_MCC_TYPE(*((u_int8_t *)(hdr + 1))), cr,
2475 length, s->state, s->flags, s->mtu, m0->m_pkthdr.len);
2476 NG_FREE_M(m0);
2477 break;
2478
2479 default:
2481"%s: Got unknown MCC, type=%#x, cr=%d, length=%d, session state=%d, " \
2482"flags=%#x, mtu=%d, len=%d\n",
2483 __func__, type, cr, length, s->state, s->flags,
2484 s->mtu, m0->m_pkthdr.len);
2485
2486 /* Reuse mbuf to send NSC */
2487 hdr = mtod(m0, struct rfcomm_mcc_hdr *);
2488 m0->m_pkthdr.len = m0->m_len = sizeof(*hdr);
2489
2490 /* Create MCC NSC header */
2492 hdr->length = RFCOMM_MKLEN8(1);
2493
2494 /* Put back MCC command type we did not like */
2495 m0->m_data[m0->m_len] = RFCOMM_MKMCC_TYPE(cr, type);
2496 m0->m_pkthdr.len ++;
2497 m0->m_len ++;
2498
2499 /* Send UIH frame */
2501 RFCOMM_MKADDRESS(INITIATOR(s), 0), 0, 0, m0));
2502 /* NOT REACHED */
2503 }
2504
2505 return (0);
2506} /* ng_btsocket_rfcomm_receive_mcc */
2507
2508/*
2509 * Receive RFCOMM TEST MCC command
2510 */
2511
2512static int
2514{
2515 struct rfcomm_mcc_hdr *hdr = mtod(m0, struct rfcomm_mcc_hdr *);
2516 int error = 0;
2517
2518 mtx_assert(&s->session_mtx, MA_OWNED);
2519
2521"%s: Got MCC TEST, cr=%d, length=%d, session state=%d, flags=%#x, mtu=%d, " \
2522"len=%d\n", __func__, RFCOMM_CR(hdr->type), RFCOMM_MCC_LENGTH(hdr->length),
2523 s->state, s->flags, s->mtu, m0->m_pkthdr.len);
2524
2525 if (RFCOMM_CR(hdr->type)) {
2528 RFCOMM_MKADDRESS(INITIATOR(s), 0), 0, 0, m0);
2529 } else
2530 NG_FREE_M(m0); /* XXX ignore response */
2531
2532 return (error);
2533} /* ng_btsocket_rfcomm_receive_test */
2534
2535/*
2536 * Receive RFCOMM FCON/FCOFF MCC command
2537 */
2538
2539static int
2541{
2542 struct rfcomm_mcc_hdr *hdr = mtod(m0, struct rfcomm_mcc_hdr *);
2543 u_int8_t type = RFCOMM_MCC_TYPE(hdr->type);
2544 int error = 0;
2545
2546 mtx_assert(&s->session_mtx, MA_OWNED);
2547
2548 /*
2549 * Turn ON/OFF aggregate flow on the entire session. When remote peer
2550 * asserted flow control no transmission shall occur except on dlci 0
2551 * (control channel).
2552 */
2553
2555"%s: Got MCC FC%s, cr=%d, length=%d, session state=%d, flags=%#x, mtu=%d, " \
2556"len=%d\n", __func__, (type == RFCOMM_MCC_FCON)? "ON" : "OFF",
2558 s->state, s->flags, s->mtu, m0->m_pkthdr.len);
2559
2560 if (RFCOMM_CR(hdr->type)) {
2561 if (type == RFCOMM_MCC_FCON)
2562 s->flags &= ~NG_BTSOCKET_RFCOMM_SESSION_RFC;
2563 else
2565
2566 hdr->type = RFCOMM_MKMCC_TYPE(0, type);
2568 RFCOMM_MKADDRESS(INITIATOR(s), 0), 0, 0, m0);
2569 } else
2570 NG_FREE_M(m0); /* XXX ignore response */
2571
2572 return (error);
2573} /* ng_btsocket_rfcomm_receive_fc */
2574
2575/*
2576 * Receive RFCOMM MSC MCC command
2577 */
2578
2579static int
2581{
2582 struct rfcomm_mcc_hdr *hdr = mtod(m0, struct rfcomm_mcc_hdr*);
2583 struct rfcomm_mcc_msc *msc = (struct rfcomm_mcc_msc *)(hdr+1);
2584 ng_btsocket_rfcomm_pcb_t *pcb = NULL;
2585 int error = 0;
2586
2587 mtx_assert(&s->session_mtx, MA_OWNED);
2588
2590"%s: Got MCC MSC, dlci=%d, cr=%d, length=%d, session state=%d, flags=%#x, " \
2591"mtu=%d, len=%d\n",
2592 __func__, RFCOMM_DLCI(msc->address), RFCOMM_CR(hdr->type),
2593 RFCOMM_MCC_LENGTH(hdr->length), s->state, s->flags,
2594 s->mtu, m0->m_pkthdr.len);
2595
2596 if (RFCOMM_CR(hdr->type)) {
2598 if (pcb == NULL) {
2600"%s: Got MSC command for non-existing dlci=%d\n",
2601 __func__, RFCOMM_DLCI(msc->address));
2602 NG_FREE_M(m0);
2603
2604 return (ENOENT);
2605 }
2606
2607 mtx_lock(&pcb->pcb_mtx);
2608
2612"%s: Got MSC on dlci=%d in invalid state=%d\n",
2613 __func__, RFCOMM_DLCI(msc->address),
2614 pcb->state);
2615
2616 mtx_unlock(&pcb->pcb_mtx);
2617 NG_FREE_M(m0);
2618
2619 return (EINVAL);
2620 }
2621
2622 pcb->rmodem = msc->modem; /* Update remote port signals */
2623
2626 RFCOMM_MKADDRESS(INITIATOR(s), 0), 0, 0, m0);
2627
2628#if 0 /* YYY */
2629 /* Send more data from DLC. XXX check for errors? */
2630 if (!(pcb->rmodem & RFCOMM_MODEM_FC) &&
2633#endif /* YYY */
2634
2635 mtx_unlock(&pcb->pcb_mtx);
2636 } else
2637 NG_FREE_M(m0); /* XXX ignore response */
2638
2639 return (error);
2640} /* ng_btsocket_rfcomm_receive_msc */
2641
2642/*
2643 * Receive RFCOMM RPN MCC command
2644 * XXX FIXME do we need htole16/le16toh for RPN param_mask?
2645 */
2646
2647static int
2649{
2650 struct rfcomm_mcc_hdr *hdr = mtod(m0, struct rfcomm_mcc_hdr *);
2651 struct rfcomm_mcc_rpn *rpn = (struct rfcomm_mcc_rpn *)(hdr + 1);
2652 int error = 0;
2653 u_int16_t param_mask;
2654 u_int8_t bit_rate, data_bits, stop_bits, parity,
2656
2657 mtx_assert(&s->session_mtx, MA_OWNED);
2658
2660"%s: Got MCC RPN, dlci=%d, cr=%d, length=%d, session state=%d, flags=%#x, " \
2661"mtu=%d, len=%d\n",
2662 __func__, RFCOMM_DLCI(rpn->dlci), RFCOMM_CR(hdr->type),
2663 RFCOMM_MCC_LENGTH(hdr->length), s->state, s->flags,
2664 s->mtu, m0->m_pkthdr.len);
2665
2666 if (RFCOMM_CR(hdr->type)) {
2668
2669 if (RFCOMM_MCC_LENGTH(hdr->length) == 1) {
2670 /* Request - return default setting */
2672 data_bits = RFCOMM_RPN_DATA_8;
2673 stop_bits = RFCOMM_RPN_STOP_1;
2674 parity = RFCOMM_RPN_PARITY_NONE;
2678 } else {
2679 /*
2680 * Ignore/accept bit_rate, 8 bits, 1 stop bit, no
2681 * parity, no flow control lines, default XON/XOFF
2682 * chars.
2683 */
2684
2685 bit_rate = rpn->bit_rate;
2686 rpn->param_mask = le16toh(rpn->param_mask); /* XXX */
2687
2688 data_bits = RFCOMM_RPN_DATA_BITS(rpn->line_settings);
2689 if (rpn->param_mask & RFCOMM_RPN_PM_DATA &&
2690 data_bits != RFCOMM_RPN_DATA_8) {
2691 data_bits = RFCOMM_RPN_DATA_8;
2693 }
2694
2695 stop_bits = RFCOMM_RPN_STOP_BITS(rpn->line_settings);
2696 if (rpn->param_mask & RFCOMM_RPN_PM_STOP &&
2697 stop_bits != RFCOMM_RPN_STOP_1) {
2698 stop_bits = RFCOMM_RPN_STOP_1;
2700 }
2701
2702 parity = RFCOMM_RPN_PARITY(rpn->line_settings);
2703 if (rpn->param_mask & RFCOMM_RPN_PM_PARITY &&
2704 parity != RFCOMM_RPN_PARITY_NONE) {
2705 parity = RFCOMM_RPN_PARITY_NONE;
2707 }
2708
2710 if (rpn->param_mask & RFCOMM_RPN_PM_FLOW &&
2714 }
2715
2716 xon_char = rpn->xon_char;
2717 if (rpn->param_mask & RFCOMM_RPN_PM_XON &&
2721 }
2722
2723 xoff_char = rpn->xoff_char;
2724 if (rpn->param_mask & RFCOMM_RPN_PM_XOFF &&
2728 }
2729 }
2730
2731 rpn->bit_rate = bit_rate;
2732 rpn->line_settings = RFCOMM_MKRPN_LINE_SETTINGS(data_bits,
2733 stop_bits, parity);
2735 rpn->xon_char = xon_char;
2736 rpn->xoff_char = xoff_char;
2737 rpn->param_mask = htole16(param_mask); /* XXX */
2738
2739 m0->m_pkthdr.len = m0->m_len = sizeof(*hdr) + sizeof(*rpn);
2740
2743 RFCOMM_MKADDRESS(INITIATOR(s), 0), 0, 0, m0);
2744 } else
2745 NG_FREE_M(m0); /* XXX ignore response */
2746
2747 return (error);
2748} /* ng_btsocket_rfcomm_receive_rpn */
2749
2750/*
2751 * Receive RFCOMM RLS MCC command
2752 */
2753
2754static int
2756{
2757 struct rfcomm_mcc_hdr *hdr = mtod(m0, struct rfcomm_mcc_hdr *);
2758 struct rfcomm_mcc_rls *rls = (struct rfcomm_mcc_rls *)(hdr + 1);
2759 int error = 0;
2760
2761 mtx_assert(&s->session_mtx, MA_OWNED);
2762
2763 /*
2764 * XXX FIXME Do we have to do anything else here? Remote peer tries to
2765 * tell us something about DLCI. Just report what we have received and
2766 * return back received values as required by TS 07.10 spec.
2767 */
2768
2770"%s: Got MCC RLS, dlci=%d, status=%#x, cr=%d, length=%d, session state=%d, " \
2771"flags=%#x, mtu=%d, len=%d\n",
2772 __func__, RFCOMM_DLCI(rls->address), rls->status,
2774 s->state, s->flags, s->mtu, m0->m_pkthdr.len);
2775
2776 if (RFCOMM_CR(hdr->type)) {
2777 if (rls->status & 0x1)
2779"%s: Got RLS dlci=%d, error=%#x\n", __func__, RFCOMM_DLCI(rls->address),
2780 rls->status >> 1);
2781
2784 RFCOMM_MKADDRESS(INITIATOR(s), 0), 0, 0, m0);
2785 } else
2786 NG_FREE_M(m0); /* XXX ignore responses */
2787
2788 return (error);
2789} /* ng_btsocket_rfcomm_receive_rls */
2790
2791/*
2792 * Receive RFCOMM PN MCC command
2793 */
2794
2795static int
2797{
2798 struct rfcomm_mcc_hdr *hdr = mtod(m0, struct rfcomm_mcc_hdr*);
2799 struct rfcomm_mcc_pn *pn = (struct rfcomm_mcc_pn *)(hdr+1);
2800 ng_btsocket_rfcomm_pcb_t *pcb = NULL;
2801 int error = 0;
2802
2803 mtx_assert(&s->session_mtx, MA_OWNED);
2804
2806"%s: Got MCC PN, dlci=%d, cr=%d, length=%d, flow_control=%#x, priority=%d, " \
2807"ack_timer=%d, mtu=%d, max_retrans=%d, credits=%d, session state=%d, " \
2808"flags=%#x, session mtu=%d, len=%d\n",
2809 __func__, pn->dlci, RFCOMM_CR(hdr->type),
2811 pn->ack_timer, le16toh(pn->mtu), pn->max_retrans, pn->credits,
2812 s->state, s->flags, s->mtu, m0->m_pkthdr.len);
2813
2814 if (pn->dlci == 0) {
2815 NG_BTSOCKET_RFCOMM_ERR("%s: Zero dlci in MCC PN\n", __func__);
2816 NG_FREE_M(m0);
2817
2818 return (EINVAL);
2819 }
2820
2821 /* Check if we have this dlci */
2823 if (pcb != NULL) {
2824 mtx_lock(&pcb->pcb_mtx);
2825
2826 if (RFCOMM_CR(hdr->type)) {
2827 /* PN Request */
2829 pn->credits, pn->mtu);
2830
2831 if (pcb->flags & NG_BTSOCKET_RFCOMM_DLC_CFC) {
2832 pn->flow_control = 0xe0;
2834 } else {
2835 pn->flow_control = 0;
2836 pn->credits = 0;
2837 }
2838
2840 error = ng_btsocket_rfcomm_send_uih(s,
2842 0, 0, m0);
2843 } else {
2844 /* PN Response - proceed with SABM. Timeout still set */
2847 pn->flow_control, pn->credits, pn->mtu);
2848
2851 RFCOMM_FRAME_SABM, pn->dlci);
2852 } else
2854"%s: Got PN response for dlci=%d in invalid state=%d\n",
2855 __func__, pn->dlci, pcb->state);
2856
2857 NG_FREE_M(m0);
2858 }
2859
2860 mtx_unlock(&pcb->pcb_mtx);
2861 } else if (RFCOMM_CR(hdr->type)) {
2862 /* PN request to non-existing dlci - incoming connection */
2864 RFCOMM_SRVCHANNEL(pn->dlci));
2865 if (pcb != NULL) {
2866 mtx_lock(&pcb->pcb_mtx);
2867
2868 pcb->dlci = pn->dlci;
2869
2871 pn->credits, pn->mtu);
2872
2873 if (pcb->flags & NG_BTSOCKET_RFCOMM_DLC_CFC) {
2874 pn->flow_control = 0xe0;
2876 } else {
2877 pn->flow_control = 0;
2878 pn->credits = 0;
2879 }
2880
2882 error = ng_btsocket_rfcomm_send_uih(s,
2884 0, 0, m0);
2885
2886 if (error == 0) {
2889 soisconnecting(pcb->so);
2890 } else
2891 ng_btsocket_rfcomm_pcb_kill(pcb, error);
2892
2893 mtx_unlock(&pcb->pcb_mtx);
2894 } else {
2895 /* Nobody is listen()ing on this channel */
2897 RFCOMM_FRAME_DM, pn->dlci);
2898 NG_FREE_M(m0);
2899 }
2900 } else
2901 NG_FREE_M(m0); /* XXX ignore response to non-existing dlci */
2902
2903 return (error);
2904} /* ng_btsocket_rfcomm_receive_pn */
2905
2906/*
2907 * Set PN parameters for dlci. Caller must hold pcb->pcb_mtx.
2908 *
2909 * From Bluetooth spec.
2910 *
2911 * "... The CL1 - CL4 field is completely redefined. (In TS07.10 this defines
2912 * the convergence layer to use, which is not applicable to RFCOMM. In RFCOMM,
2913 * in Bluetooth versions up to 1.0B, this field was forced to 0).
2914 *
2915 * In the PN request sent prior to a DLC establishment, this field must contain
2916 * the value 15 (0xF), indicating support of credit based flow control in the
2917 * sender. See Table 5.3 below. If the PN response contains any other value
2918 * than 14 (0xE) in this field, it is inferred that the peer RFCOMM entity is
2919 * not supporting the credit based flow control feature. (This is only possible
2920 * if the peer RFCOMM implementation is only conforming to Bluetooth version
2921 * 1.0B.) If a PN request is sent on an already open DLC, then this field must
2922 * contain the value zero; it is not possible to set initial credits more
2923 * than once per DLC activation. A responding implementation must set this
2924 * field in the PN response to 14 (0xE), if (and only if) the value in the PN
2925 * request was 15..."
2926 */
2927
2928static void
2930 u_int8_t flow_control, u_int8_t credits, u_int16_t mtu)
2931{
2932 mtx_assert(&pcb->pcb_mtx, MA_OWNED);
2933
2934 pcb->mtu = le16toh(mtu);
2935
2936 if (cr) {
2937 if (flow_control == 0xf0) {
2939 pcb->tx_cred = credits;
2940 } else {
2941 pcb->flags &= ~NG_BTSOCKET_RFCOMM_DLC_CFC;
2942 pcb->tx_cred = 0;
2943 }
2944 } else {
2945 if (flow_control == 0xe0) {
2947 pcb->tx_cred = credits;
2948 } else {
2949 pcb->flags &= ~NG_BTSOCKET_RFCOMM_DLC_CFC;
2950 pcb->tx_cred = 0;
2951 }
2952 }
2953
2955"%s: cr=%d, dlci=%d, state=%d, flags=%#x, mtu=%d, rx_cred=%d, tx_cred=%d\n",
2956 __func__, cr, pcb->dlci, pcb->state, pcb->flags, pcb->mtu,
2957 pcb->rx_cred, pcb->tx_cred);
2958} /* ng_btsocket_rfcomm_set_pn */
2959
2960/*
2961 * Send RFCOMM SABM/DISC/UA/DM frames. Caller must hold s->session_mtx
2962 */
2963
2964static int
2966 u_int8_t type, u_int8_t dlci)
2967{
2968 struct rfcomm_cmd_hdr *hdr = NULL;
2969 struct mbuf *m = NULL;
2970 int cr;
2971
2972 mtx_assert(&s->session_mtx, MA_OWNED);
2973
2975"%s: Sending command type %#x, session state=%d, flags=%#x, mtu=%d, dlci=%d\n",
2976 __func__, type, s->state, s->flags, s->mtu, dlci);
2977
2978 switch (type) {
2979 case RFCOMM_FRAME_SABM:
2980 case RFCOMM_FRAME_DISC:
2981 cr = INITIATOR(s);
2982 break;
2983
2984 case RFCOMM_FRAME_UA:
2985 case RFCOMM_FRAME_DM:
2986 cr = !INITIATOR(s);
2987 break;
2988
2989 default:
2990 panic("%s: Invalid frame type=%#x\n", __func__, type);
2991 return (EINVAL);
2992 /* NOT REACHED */
2993 }
2994
2995 MGETHDR(m, M_NOWAIT, MT_DATA);
2996 if (m == NULL)
2997 return (ENOBUFS);
2998
2999 m->m_pkthdr.len = m->m_len = sizeof(*hdr);
3000
3001 hdr = mtod(m, struct rfcomm_cmd_hdr *);
3002 hdr->address = RFCOMM_MKADDRESS(cr, dlci);
3003 hdr->control = RFCOMM_MKCONTROL(type, 1);
3004 hdr->length = RFCOMM_MKLEN8(0);
3005 hdr->fcs = ng_btsocket_rfcomm_fcs3((u_int8_t *) hdr);
3006
3007 NG_BT_MBUFQ_ENQUEUE(&s->outq, m);
3008
3009 return (0);
3010} /* ng_btsocket_rfcomm_send_command */
3011
3012/*
3013 * Send RFCOMM UIH frame. Caller must hold s->session_mtx
3014 */
3015
3016static int
3018 u_int8_t pf, u_int8_t credits, struct mbuf *data)
3019{
3020 struct rfcomm_frame_hdr *hdr = NULL;
3021 struct mbuf *m = NULL, *mcrc = NULL;
3022 u_int16_t length;
3023
3024 mtx_assert(&s->session_mtx, MA_OWNED);
3025
3026 MGETHDR(m, M_NOWAIT, MT_DATA);
3027 if (m == NULL) {
3028 NG_FREE_M(data);
3029 return (ENOBUFS);
3030 }
3031 m->m_pkthdr.len = m->m_len = sizeof(*hdr);
3032
3033 MGET(mcrc, M_NOWAIT, MT_DATA);
3034 if (mcrc == NULL) {
3035 NG_FREE_M(data);
3036 return (ENOBUFS);
3037 }
3038 mcrc->m_len = 1;
3039
3040 /* Fill UIH frame header */
3041 hdr = mtod(m, struct rfcomm_frame_hdr *);
3042 hdr->address = address;
3044
3045 /* Calculate FCS */
3046 mcrc->m_data[0] = ng_btsocket_rfcomm_fcs2((u_int8_t *) hdr);
3047
3048 /* Put length back */
3049 length = (data != NULL)? data->m_pkthdr.len : 0;
3050 if (length > 127) {
3051 u_int16_t l = htole16(RFCOMM_MKLEN16(length));
3052
3053 bcopy(&l, &hdr->length, sizeof(l));
3054 m->m_pkthdr.len ++;
3055 m->m_len ++;
3056 } else
3057 hdr->length = RFCOMM_MKLEN8(length);
3058
3059 if (pf) {
3060 m->m_data[m->m_len] = credits;
3061 m->m_pkthdr.len ++;
3062 m->m_len ++;
3063 }
3064
3065 /* Add payload */
3066 if (data != NULL) {
3067 m_cat(m, data);
3068 m->m_pkthdr.len += length;
3069 }
3070
3071 /* Put FCS back */
3072 m_cat(m, mcrc);
3073 m->m_pkthdr.len ++;
3074
3076"%s: Sending UIH state=%d, flags=%#x, address=%d, length=%d, pf=%d, " \
3077"credits=%d, len=%d\n",
3078 __func__, s->state, s->flags, address, length, pf, credits,
3079 m->m_pkthdr.len);
3080
3081 NG_BT_MBUFQ_ENQUEUE(&s->outq, m);
3082
3083 return (0);
3084} /* ng_btsocket_rfcomm_send_uih */
3085
3086/*
3087 * Send MSC request. Caller must hold pcb->pcb_mtx and pcb->session->session_mtx
3088 */
3089
3090static int
3092{
3093 struct mbuf *m = NULL;
3094 struct rfcomm_mcc_hdr *hdr = NULL;
3095 struct rfcomm_mcc_msc *msc = NULL;
3096
3097 mtx_assert(&pcb->session->session_mtx, MA_OWNED);
3098 mtx_assert(&pcb->pcb_mtx, MA_OWNED);
3099
3100 MGETHDR(m, M_NOWAIT, MT_DATA);
3101 if (m == NULL)
3102 return (ENOBUFS);
3103
3104 m->m_pkthdr.len = m->m_len = sizeof(*hdr) + sizeof(*msc);
3105
3106 hdr = mtod(m, struct rfcomm_mcc_hdr *);
3107 msc = (struct rfcomm_mcc_msc *)(hdr + 1);
3108
3110 hdr->length = RFCOMM_MKLEN8(sizeof(*msc));
3111
3112 msc->address = RFCOMM_MKADDRESS(1, pcb->dlci);
3113 msc->modem = pcb->lmodem;
3114
3116"%s: Sending MSC dlci=%d, state=%d, flags=%#x, address=%d, modem=%#x\n",
3117 __func__, pcb->dlci, pcb->state, pcb->flags, msc->address,
3118 msc->modem);
3119
3121 RFCOMM_MKADDRESS(INITIATOR(pcb->session), 0), 0, 0, m));
3122} /* ng_btsocket_rfcomm_send_msc */
3123
3124/*
3125 * Send PN request. Caller must hold pcb->pcb_mtx and pcb->session->session_mtx
3126 */
3127
3128static int
3130{
3131 struct mbuf *m = NULL;
3132 struct rfcomm_mcc_hdr *hdr = NULL;
3133 struct rfcomm_mcc_pn *pn = NULL;
3134
3135 mtx_assert(&pcb->session->session_mtx, MA_OWNED);
3136 mtx_assert(&pcb->pcb_mtx, MA_OWNED);
3137
3138 MGETHDR(m, M_NOWAIT, MT_DATA);
3139 if (m == NULL)
3140 return (ENOBUFS);
3141
3142 m->m_pkthdr.len = m->m_len = sizeof(*hdr) + sizeof(*pn);
3143
3144 hdr = mtod(m, struct rfcomm_mcc_hdr *);
3145 pn = (struct rfcomm_mcc_pn *)(hdr + 1);
3146
3148 hdr->length = RFCOMM_MKLEN8(sizeof(*pn));
3149
3150 pn->dlci = pcb->dlci;
3151
3152 /*
3153 * Set default DLCI priority as described in GSM 07.10
3154 * (ETSI TS 101 369) clause 5.6 page 42
3155 */
3156
3157 pn->priority = (pcb->dlci < 56)? (((pcb->dlci >> 3) << 3) + 7) : 61;
3158 pn->ack_timer = 0;
3159 pn->mtu = htole16(pcb->mtu);
3160 pn->max_retrans = 0;
3161
3162 if (pcb->flags & NG_BTSOCKET_RFCOMM_DLC_CFC) {
3163 pn->flow_control = 0xf0;
3164 pn->credits = pcb->rx_cred;
3165 } else {
3166 pn->flow_control = 0;
3167 pn->credits = 0;
3168 }
3169
3171"%s: Sending PN dlci=%d, state=%d, flags=%#x, mtu=%d, flow_control=%#x, " \
3172"credits=%d\n", __func__, pcb->dlci, pcb->state, pcb->flags, pcb->mtu,
3173 pn->flow_control, pn->credits);
3174
3176 RFCOMM_MKADDRESS(INITIATOR(pcb->session), 0), 0, 0, m));
3177} /* ng_btsocket_rfcomm_send_pn */
3178
3179/*
3180 * Calculate and send credits based on available space in receive buffer
3181 */
3182
3183static int
3185{
3186 int error = 0;
3187 u_int8_t credits;
3188
3189 mtx_assert(&pcb->pcb_mtx, MA_OWNED);
3190 mtx_assert(&pcb->session->session_mtx, MA_OWNED);
3191
3193"%s: Sending more credits, dlci=%d, state=%d, flags=%#x, mtu=%d, " \
3194"space=%ld, tx_cred=%d, rx_cred=%d\n",
3195 __func__, pcb->dlci, pcb->state, pcb->flags, pcb->mtu,
3196 sbspace(&pcb->so->so_rcv), pcb->tx_cred, pcb->rx_cred);
3197
3198 credits = sbspace(&pcb->so->so_rcv) / pcb->mtu;
3199 if (credits > 0) {
3200 if (pcb->rx_cred + credits > RFCOMM_MAX_CREDITS)
3202
3204 pcb->session,
3206 pcb->dlci), 1, credits, NULL);
3207 if (error == 0) {
3208 pcb->rx_cred += credits;
3209
3211"%s: Gave remote side %d more credits, dlci=%d, state=%d, flags=%#x, " \
3212"rx_cred=%d, tx_cred=%d\n", __func__, credits, pcb->dlci, pcb->state,
3213 pcb->flags, pcb->rx_cred, pcb->tx_cred);
3214 } else
3216"%s: Could not send credits, error=%d, dlci=%d, state=%d, flags=%#x, " \
3217"mtu=%d, space=%ld, tx_cred=%d, rx_cred=%d\n",
3218 __func__, error, pcb->dlci, pcb->state,
3219 pcb->flags, pcb->mtu, sbspace(&pcb->so->so_rcv),
3220 pcb->tx_cred, pcb->rx_cred);
3221 }
3222
3223 return (error);
3224} /* ng_btsocket_rfcomm_send_credits */
3225
3226/*****************************************************************************
3227 *****************************************************************************
3228 ** RFCOMM DLCs
3229 *****************************************************************************
3230 *****************************************************************************/
3231
3232/*
3233 * Send data from socket send buffer
3234 * Caller must hold pcb->pcb_mtx and pcb->session->session_mtx
3235 */
3236
3237static int
3239{
3240 struct mbuf *m = NULL;
3241 int sent, length, error;
3242
3243 mtx_assert(&pcb->session->session_mtx, MA_OWNED);
3244 mtx_assert(&pcb->pcb_mtx, MA_OWNED);
3245
3247 limit = min(limit, pcb->tx_cred);
3248 else if (!(pcb->rmodem & RFCOMM_MODEM_FC))
3249 limit = min(limit, RFCOMM_MAX_CREDITS); /* XXX ??? */
3250 else
3251 limit = 0;
3252
3253 if (limit == 0) {
3255"%s: Could not send - remote flow control asserted, dlci=%d, flags=%#x, " \
3256"rmodem=%#x, tx_cred=%d\n",
3257 __func__, pcb->dlci, pcb->flags, pcb->rmodem,
3258 pcb->tx_cred);
3259
3260 return (0);
3261 }
3262
3263 for (error = 0, sent = 0; sent < limit; sent ++) {
3264 length = min(pcb->mtu, sbavail(&pcb->so->so_snd));
3265 if (length == 0)
3266 break;
3267
3268 /* Get the chunk from the socket's send buffer */
3269 m = ng_btsocket_rfcomm_prepare_packet(&pcb->so->so_snd, length);
3270 if (m == NULL) {
3271 error = ENOBUFS;
3272 break;
3273 }
3274
3275 sbdrop(&pcb->so->so_snd, length);
3276
3279 pcb->dlci), 0, 0, m);
3280 if (error != 0)
3281 break;
3282 }
3283
3285 pcb->tx_cred -= sent;
3286
3287 if (error == 0 && sent > 0) {
3288 pcb->flags &= ~NG_BTSOCKET_RFCOMM_DLC_SENDING;
3289 sowwakeup(pcb->so);
3290 }
3291
3292 return (error);
3293} /* ng_btsocket_rfcomm_pcb_send */
3294
3295/*
3296 * Unlink and disconnect DLC. If ng_btsocket_rfcomm_pcb_kill() returns
3297 * non zero value than socket has no reference and has to be detached.
3298 * Caller must hold pcb->pcb_mtx and pcb->session->session_mtx
3299 */
3300
3301static void
3303{
3305
3307"%s: Killing DLC, so=%p, dlci=%d, state=%d, flags=%#x, error=%d\n",
3308 __func__, pcb->so, pcb->dlci, pcb->state, pcb->flags, error);
3309
3310 if (pcb->session == NULL)
3311 panic("%s: DLC without session, pcb=%p, state=%d, flags=%#x\n",
3312 __func__, pcb, pcb->state, pcb->flags);
3313
3314 mtx_assert(&pcb->session->session_mtx, MA_OWNED);
3315 mtx_assert(&pcb->pcb_mtx, MA_OWNED);
3316
3319
3320 /* Detach DLC from the session. Does not matter which state DLC in */
3321 LIST_REMOVE(pcb, session_next);
3322 pcb->session = NULL;
3323
3324 /* Change DLC state and wakeup all sleepers */
3326 pcb->so->so_error = error;
3327 soisdisconnected(pcb->so);
3328 wakeup(&pcb->state);
3329
3330 /* Check if we have any DLCs left on the session */
3331 if (LIST_EMPTY(&s->dlcs) && INITIATOR(s)) {
3333"%s: Disconnecting session, state=%d, flags=%#x, mtu=%d\n",
3334 __func__, s->state, s->flags, s->mtu);
3335
3336 switch (s->state) {
3339 /*
3340 * Do not have to do anything here. We can get here
3341 * when L2CAP connection was terminated or we have
3342 * received DISC on multiplexor channel
3343 */
3344 break;
3345
3347 /* Send DISC on multiplexor channel */
3350 if (error == 0) {
3352 break;
3353 }
3354 /* FALL THROUGH */
3355
3359 break;
3360
3361/* case NG_BTSOCKET_RFCOMM_SESSION_LISTENING: */
3362 default:
3363 panic("%s: Invalid session state=%d, flags=%#x\n",
3364 __func__, s->state, s->flags);
3365 break;
3366 }
3367
3369 }
3370} /* ng_btsocket_rfcomm_pcb_kill */
3371
3372/*
3373 * Look for given dlci for given RFCOMM session. Caller must hold s->session_mtx
3374 */
3375
3378{
3379 ng_btsocket_rfcomm_pcb_p pcb = NULL;
3380
3381 mtx_assert(&s->session_mtx, MA_OWNED);
3382
3383 LIST_FOREACH(pcb, &s->dlcs, session_next)
3384 if (pcb->dlci == dlci)
3385 break;
3386
3387 return (pcb);
3388} /* ng_btsocket_rfcomm_pcb_by_dlci */
3389
3390/*
3391 * Look for socket that listens on given src address and given channel
3392 */
3393
3396{
3397 ng_btsocket_rfcomm_pcb_p pcb = NULL, pcb1 = NULL;
3398
3399 mtx_lock(&ng_btsocket_rfcomm_sockets_mtx);
3400
3401 LIST_FOREACH(pcb, &ng_btsocket_rfcomm_sockets, next) {
3402 if (pcb->channel != channel || !SOLISTENING(pcb->so))
3403 continue;
3404
3405 if (bcmp(&pcb->src, src, sizeof(*src)) == 0)
3406 break;
3407
3408 if (bcmp(&pcb->src, NG_HCI_BDADDR_ANY, sizeof(bdaddr_t)) == 0)
3409 pcb1 = pcb;
3410 }
3411
3412 mtx_unlock(&ng_btsocket_rfcomm_sockets_mtx);
3413
3414 return ((pcb != NULL)? pcb : pcb1);
3415} /* ng_btsocket_rfcomm_pcb_listener */
3416
3417/*****************************************************************************
3418 *****************************************************************************
3419 ** Misc. functions
3420 *****************************************************************************
3421 *****************************************************************************/
3422
3423/*
3424 * Set timeout. Caller MUST hold pcb_mtx
3425 */
3426
3427static void
3429{
3430 mtx_assert(&pcb->pcb_mtx, MA_OWNED);
3431
3432 if (!(pcb->flags & NG_BTSOCKET_RFCOMM_DLC_TIMO)) {
3434 pcb->flags &= ~NG_BTSOCKET_RFCOMM_DLC_TIMEDOUT;
3435 callout_reset(&pcb->timo, ng_btsocket_rfcomm_timo * hz,
3437 } else
3438 panic("%s: Duplicated socket timeout?!\n", __func__);
3439} /* ng_btsocket_rfcomm_timeout */
3440
3441/*
3442 * Unset pcb timeout. Caller MUST hold pcb_mtx
3443 */
3444
3445static void
3447{
3448 mtx_assert(&pcb->pcb_mtx, MA_OWNED);
3449
3451 callout_stop(&pcb->timo);
3452 pcb->flags &= ~NG_BTSOCKET_RFCOMM_DLC_TIMO;
3453 pcb->flags &= ~NG_BTSOCKET_RFCOMM_DLC_TIMEDOUT;
3454 } else
3455 panic("%s: No socket timeout?!\n", __func__);
3456} /* ng_btsocket_rfcomm_timeout */
3457
3458/*
3459 * Process pcb timeout
3460 */
3461
3462static void
3464{
3466
3467 mtx_assert(&pcb->pcb_mtx, MA_OWNED);
3468
3470"%s: Timeout, so=%p, dlci=%d, state=%d, flags=%#x\n",
3471 __func__, pcb->so, pcb->dlci, pcb->state, pcb->flags);
3472
3473 pcb->flags &= ~NG_BTSOCKET_RFCOMM_DLC_TIMO;
3475
3476 switch (pcb->state) {
3480 break;
3481
3484 break;
3485
3486 default:
3487 panic(
3488"%s: DLC timeout in invalid state, dlci=%d, state=%d, flags=%#x\n",
3489 __func__, pcb->dlci, pcb->state, pcb->flags);
3490 break;
3491 }
3492
3494} /* ng_btsocket_rfcomm_process_timeout */
3495
3496/*
3497 * Get up to length bytes from the socket buffer
3498 */
3499
3500static struct mbuf *
3502{
3503 struct mbuf *top = NULL, *m = NULL, *n = NULL, *nextpkt = NULL;
3504 int mlen, noff, len;
3505
3506 MGETHDR(top, M_NOWAIT, MT_DATA);
3507 if (top == NULL)
3508 return (NULL);
3509
3510 top->m_pkthdr.len = length;
3511 top->m_len = 0;
3512 mlen = MHLEN;
3513
3514 m = top;
3515 n = sb->sb_mb;
3516 nextpkt = n->m_nextpkt;
3517 noff = 0;
3518
3519 while (length > 0 && n != NULL) {
3520 len = min(mlen - m->m_len, n->m_len - noff);
3521 if (len > length)
3522 len = length;
3523
3524 bcopy(mtod(n, caddr_t)+noff, mtod(m, caddr_t)+m->m_len, len);
3525 m->m_len += len;
3526 noff += len;
3527 length -= len;
3528
3529 if (length > 0 && m->m_len == mlen) {
3530 MGET(m->m_next, M_NOWAIT, MT_DATA);
3531 if (m->m_next == NULL) {
3532 NG_FREE_M(top);
3533 return (NULL);
3534 }
3535
3536 m = m->m_next;
3537 m->m_len = 0;
3538 mlen = MLEN;
3539 }
3540
3541 if (noff == n->m_len) {
3542 noff = 0;
3543 n = n->m_next;
3544
3545 if (n == NULL)
3546 n = nextpkt;
3547
3548 nextpkt = (n != NULL)? n->m_nextpkt : NULL;
3549 }
3550 }
3551
3552 if (length < 0)
3553 panic("%s: length=%d\n", __func__, length);
3554 if (length > 0 && n == NULL)
3555 panic("%s: bogus length=%d, n=%p\n", __func__, length, n);
3556
3557 return (top);
3558} /* ng_btsocket_rfcomm_prepare_packet */
uint8_t flags
Definition: netflow.h:14
#define NG_FREE_M(m)
Definition: netgraph.h:946
SYSCTL_NODE(_net, OID_AUTO, bluetooth, CTLFLAG_RW|CTLFLAG_MPSAFE, 0, "Bluetooth family")
SYSCTL_UINT(_net_bluetooth_hci, OID_AUTO, max_neighbor_age, CTLFLAG_RW, &bluetooth_hci_max_neighbor_age_value, 600, "Maximal HCI neighbor cache entry age (sec)")
#define NG_BT_MBUFQ_DRAIN(q)
Definition: ng_bluetooth.h:135
#define NG_BT_MBUFQ_DEQUEUE(q, i)
Definition: ng_bluetooth.h:112
#define NG_BT_MBUFQ_INIT(q, _maxlen)
Definition: ng_bluetooth.h:77
#define NG_BT_MBUFQ_ENQUEUE(q, i)
Definition: ng_bluetooth.h:99
#define BDADDR_BREDR
Definition: ng_bluetooth.h:229
#define SO_L2CAP_IMTU
Definition: ng_btsocket.h:249
#define NG_BTSOCKET_INFO_LEVEL
Definition: ng_btsocket.h:373
#define SO_RFCOMM_FC_INFO
Definition: ng_btsocket.h:355
#define SOL_L2CAP
Definition: ng_btsocket.h:247
#define SO_RFCOMM_MTU
Definition: ng_btsocket.h:354
#define BLUETOOTH_PROTO_L2CAP
Definition: ng_btsocket.h:44
#define SOL_RFCOMM
Definition: ng_btsocket.h:352
#define NG_BTSOCKET_WARN_LEVEL
Definition: ng_btsocket.h:372
#define BLUETOOTH_PROTO_RFCOMM
Definition: ng_btsocket.h:45
#define so2l2cap_pcb(so)
static ng_btsocket_rfcomm_pcb_p ng_btsocket_rfcomm_pcb_listener(bdaddr_p src, int channel)
static void ng_btsocket_rfcomm_init(void *arg __unused)
static int ng_btsocket_rfcomm_receive_frame(ng_btsocket_rfcomm_session_p s, struct mbuf *m0)
#define NG_BTSOCKET_RFCOMM_WARN
static int ng_btsocket_rfcomm_receive_msc(ng_btsocket_rfcomm_session_p s, struct mbuf *m0)
#define M_NETGRAPH_BTSOCKET_RFCOMM
#define ALOT
int ng_btsocket_rfcomm_send(struct socket *so, int flags, struct mbuf *m, struct sockaddr *nam, struct mbuf *control, struct thread *td)
static void ng_btsocket_rfcomm_session_task(ng_btsocket_rfcomm_session_p s)
static int ng_btsocket_rfcomm_check_fcs(u_int8_t *data, int type, u_int8_t fcs)
int ng_btsocket_rfcomm_ctloutput(struct socket *so, struct sockopt *sopt)
static int ng_btsocket_rfcomm_receive_sabm(ng_btsocket_rfcomm_session_p s, int dlci)
static void ng_btsocket_rfcomm_set_pn(ng_btsocket_rfcomm_pcb_p pcb, u_int8_t cr, u_int8_t flow_control, u_int8_t credits, u_int16_t mtu)
#define ng_btsocket_rfcomm_task_wakeup()
static int ng_btsocket_rfcomm_receive_uih(ng_btsocket_rfcomm_session_p s, int dlci, int pf, struct mbuf *m0)
static int ng_btsocket_rfcomm_receive_test(ng_btsocket_rfcomm_session_p s, struct mbuf *m0)
void ng_btsocket_rfcomm_close(struct socket *so)
static void ng_btsocket_rfcomm_timeout(ng_btsocket_rfcomm_pcb_p pcb)
int ifqmaxlen
SYSINIT(ng_btsocket_rfcomm_init, SI_SUB_PROTO_DOMAIN, SI_ORDER_THIRD, ng_btsocket_rfcomm_init, NULL)
#define NG_BTSOCKET_RFCOMM_INFO
static void ng_btsocket_rfcomm_pcb_kill(ng_btsocket_rfcomm_pcb_p pcb, int error)
static int ng_btsocket_rfcomm_upcall(struct socket *so, void *arg, int waitflag)
static void ng_btsocket_rfcomm_process_timeout(void *xpcb)
static int ng_btsocket_rfcomm_send_command(ng_btsocket_rfcomm_session_p s, u_int8_t type, u_int8_t dlci)
static ng_btsocket_rfcomm_session_p ng_btsocket_rfcomm_session_by_addr(bdaddr_p src, bdaddr_p dst)
static int ng_btsocket_rfcomm_session_accept(ng_btsocket_rfcomm_session_p s0)
int ng_btsocket_rfcomm_sockaddr(struct socket *so, struct sockaddr **nam)
static int ng_btsocket_rfcomm_session_create(ng_btsocket_rfcomm_session_p *sp, struct socket *l2so, bdaddr_p src, bdaddr_p dst, struct thread *td)
static u_int8_t ng_btsocket_rfcomm_fcs3(u_int8_t *data)
static struct mbuf * ng_btsocket_rfcomm_prepare_packet(struct sockbuf *sb, int length)
int ng_btsocket_rfcomm_disconnect(struct socket *so)
static LIST_HEAD(ng_btsocket_rfcomm_session)
int ng_btsocket_rfcomm_peeraddr(struct socket *so, struct sockaddr **nam)
struct task ng_btsocket_rfcomm_task
static int ng_btsocket_rfcomm_send_credits(ng_btsocket_rfcomm_pcb_p pcb)
static int ng_btsocket_rfcomm_receive_dm(ng_btsocket_rfcomm_session_p s, int dlci)
int ng_btsocket_rfcomm_accept(struct socket *so, struct sockaddr **nam)
static int ng_btsocket_rfcomm_receive_ua(ng_btsocket_rfcomm_session_p s, int dlci)
static int ng_btsocket_rfcomm_receive_fc(ng_btsocket_rfcomm_session_p s, struct mbuf *m0)
int ng_btsocket_rfcomm_bind(struct socket *so, struct sockaddr *nam, struct thread *td)
static int ng_btsocket_rfcomm_receive_disc(ng_btsocket_rfcomm_session_p s, int dlci)
static int ng_btsocket_rfcomm_pcb_send(ng_btsocket_rfcomm_pcb_p pcb, int limit)
static int ng_btsocket_rfcomm_send_pn(ng_btsocket_rfcomm_pcb_p pcb)
static int ng_btsocket_rfcomm_receive_pn(ng_btsocket_rfcomm_session_p s, struct mbuf *m0)
static int ng_btsocket_rfcomm_session_send(ng_btsocket_rfcomm_session_p s)
static u_int8_t ng_btsocket_rfcomm_crc(u_int8_t *data, int length)
static int ng_btsocket_rfcomm_send_uih(ng_btsocket_rfcomm_session_p s, u_int8_t address, u_int8_t pf, u_int8_t credits, struct mbuf *data)
static void ng_btsocket_rfcomm_connect_cfm(ng_btsocket_rfcomm_session_p s)
static ng_btsocket_rfcomm_pcb_p ng_btsocket_rfcomm_connect_ind(ng_btsocket_rfcomm_session_p s, int channel)
static void ng_btsocket_rfcomm_untimeout(ng_btsocket_rfcomm_pcb_p pcb)
int ng_btsocket_rfcomm_listen(struct socket *so, int backlog, struct thread *td)
void ng_btsocket_rfcomm_detach(struct socket *so)
#define NG_BTSOCKET_RFCOMM_ERR
static int ng_btsocket_rfcomm_receive_rls(ng_btsocket_rfcomm_session_p s, struct mbuf *m0)
int ng_btsocket_rfcomm_control(struct socket *so, u_long cmd, caddr_t data, struct ifnet *ifp, struct thread *td)
int ng_btsocket_rfcomm_connect(struct socket *so, struct sockaddr *nam, struct thread *td)
static u_int8_t ng_btsocket_rfcomm_fcs2(u_int8_t *data)
static u_int32_t ng_btsocket_rfcomm_timo
static int ng_btsocket_rfcomm_session_connect(ng_btsocket_rfcomm_session_p s)
void ng_btsocket_rfcomm_abort(struct socket *so)
static ng_btsocket_rfcomm_pcb_p ng_btsocket_rfcomm_pcb_by_dlci(ng_btsocket_rfcomm_session_p s, int dlci)
int ng_btsocket_rfcomm_attach(struct socket *so, int proto, struct thread *td)
static int ng_btsocket_rfcomm_receive_mcc(ng_btsocket_rfcomm_session_p s, struct mbuf *m0)
static u_int32_t ng_btsocket_rfcomm_debug_level
static int ng_btsocket_rfcomm_send_msc(ng_btsocket_rfcomm_pcb_p pcb)
static void ng_btsocket_rfcomm_sessions_task(void *ctx, int pending)
static void ng_btsocket_rfcomm_session_clean(ng_btsocket_rfcomm_session_p s)
static void ng_btsocket_rfcomm_session_process_pcb(ng_btsocket_rfcomm_session_p s)
static int ng_btsocket_rfcomm_receive_rpn(ng_btsocket_rfcomm_session_p s, struct mbuf *m0)
#define NG_BTSOCKET_RFCOMM_ALERT
static int ng_btsocket_rfcomm_session_receive(ng_btsocket_rfcomm_session_p s)
#define RFCOMM_MCC_RPN
#define NG_BTSOCKET_RFCOMM_SESSION_DISCONNECTING
#define RFCOMM_MCC_FCOFF
u_int16_t param_mask
#define RFCOMM_MKRPN_LINE_SETTINGS(data, stop, parity)
#define RFCOMM_FRAME_UIH
#define RFCOMM_MCC_TYPE(b)
#define RFCOMM_RPN_STOP_BITS(line)
#define NG_BTSOCKET_RFCOMM_SESSION_LISTENING
#define RFCOMM_RPN_DATA_8
#define NG_BTSOCKET_RFCOMM_DLC_W4_CONNECT
#define NG_BTSOCKET_RFCOMM_SESSION_CONNECTING
#define RFCOMM_RPN_PARITY(line)
#define NG_BTSOCKET_RFCOMM_DLC_CLOSED
#define RFCOMM_RPN_XON_CHAR
#define RFCOMM_MAX_CREDITS
#define RFCOMM_FRAME_SABM
u_int8_t type
#define RFCOMM_MCC_RLS
#define RFCOMM_MCC_PN
#define RFCOMM_RPN_DATA_BITS(line)
#define RFCOMM_MCC_FCON
#define NG_BTSOCKET_RFCOMM_SESSION_OPEN
#define RFCOMM_MCC_TEST
#define RFCOMM_MODEM_FC
#define RFCOMM_RPN_STOP_1
#define RFCOMM_RPN_PARITY_NONE
#define INITIATOR(s)
#define RFCOMM_MKDLCI(dir, channel)
u_int8_t credits
#define RFCOMM_RPN_PM_XON
#define RFCOMM_RPN_PM_STOP
#define RFCOMM_FRAME_DM
#define RFCOMM_DLCI(b)
#define RFCOMM_SRVCHANNEL(dlci)
#define RFCOMM_MCC_MSC
#define NG_BTSOCKET_RFCOMM_RECVSPACE
#define NG_BTSOCKET_RFCOMM_SESSION_LFC
#define RFCOMM_FRAME_DISC
#define RFCOMM_RPN_BR_115200
#define NG_BTSOCKET_RFCOMM_DLC_CONNECTED
#define NG_BTSOCKET_RFCOMM_SESSION_INITIATOR
#define NG_BTSOCKET_RFCOMM_DLC_CONNECTING
#define NG_BTSOCKET_RFCOMM_DLC_SENDING
u_int8_t xon_char
u_int8_t flow_control
u_int16_t mtu
#define RFCOMM_RPN_PM_FLOW
struct ng_btsocket_rfcomm_pcb * ng_btsocket_rfcomm_pcb_p
#define RFCOMM_MCC_NSC
#define RFCOMM_MODEM_RTR
#define RFCOMM_PF(b)
#define NG_BTSOCKET_RFCOMM_DLC_CONFIGURING
#define RFCOMM_RPN_XOFF_CHAR
#define RFCOMM_FRAME_UA
#define RFCOMM_RPN_PM_XOFF
u_int8_t fcs
#define so2rfcomm_pcb(so)
#define RFCOMM_MKLEN8(len)
#define RFCOMM_MKLEN16(len)
u_int8_t address
u_int8_t bit_rate
#define RFCOMM_CR(b)
#define NG_BTSOCKET_RFCOMM_DLC_DETACHED
u_int8_t xoff_char
#define NG_BTSOCKET_RFCOMM_DLC_TIMO
#define RFCOMM_MKMCC_TYPE(cr, type)
#define RFCOMM_MKADDRESS(cr, dlci)
#define NG_BTSOCKET_RFCOMM_DLC_DISCONNECTING
#define RFCOMM_MCC_LENGTH(b)
#define NG_BTSOCKET_RFCOMM_SESSION_CONNECTED
#define NG_BTSOCKET_RFCOMM_DLC_CFC
#define RFCOMM_MODEM_RTC
#define RFCOMM_EA(b)
#define NG_BTSOCKET_RFCOMM_SESSION_CLOSED
u_int8_t control
#define RFCOMM_RPN_PM_DATA
#define RFCOMM_TYPE(b)
#define NG_BTSOCKET_RFCOMM_SESSION_RFC
#define NG_BTSOCKET_RFCOMM_SENDSPACE
u_int8_t dlci
#define RFCOMM_DEFAULT_MTU
#define RFCOMM_RPN_FLOW_NONE
#define RFCOMM_MODEM_DV
#define RFCOMM_RPN_PM_ALL
#define RFCOMM_MKCONTROL(type, pf)
#define NG_BTSOCKET_RFCOMM_DLC_TIMEDOUT
#define RFCOMM_DEFAULT_CREDITS
#define RFCOMM_RPN_PM_PARITY
MALLOC_DEFINE(M_NG_CCATM, "ng_ccatm", "netgraph uni api node")
#define NG_HCI_BDADDR_ANY
Definition: ng_hci.h:450
bdaddr_t * bdaddr_p
Definition: ng_hci.h:447
#define min(a, b)
Definition: ng_hci_cmds.c:60
#define NG_L2CAP_PSM_RFCOMM
Definition: ng_l2cap.h:106
cmd
Definition: ng_pppoe.h:74
uint8_t length
Definition: ng_ubt_var.h:1
uint8_t data[]
Definition: ng_ubt_var.h:2
struct ng_btsocket_rfcomm_session * session
u_char l2cap_len
Definition: ng_btsocket.h:234
u_int16_t l2cap_cid
Definition: ng_btsocket.h:238
u_int8_t l2cap_bdaddr_type
Definition: ng_btsocket.h:239
u_int16_t l2cap_psm
Definition: ng_btsocket.h:236
bdaddr_t l2cap_bdaddr
Definition: ng_btsocket.h:237
u_char l2cap_family
Definition: ng_btsocket.h:235
bdaddr_t rfcomm_bdaddr
Definition: ng_btsocket.h:337
u_char rfcomm_family
Definition: ng_btsocket.h:336
u_int8_t rfcomm_channel
Definition: ng_btsocket.h:338