Home | History | Annotate | Line # | Download | only in bluetooth
bth5.c revision 1.4.2.2
      1  1.4.2.2  skrll /*	$NetBSD: bth5.c,v 1.4.2.2 2017/08/28 17:52:01 skrll Exp $	*/
      2  1.4.2.2  skrll /*
      3  1.4.2.2  skrll  * Copyright (c) 2017 Nathanial Sloss <nathanialsloss (at) yahoo.com.au>
      4  1.4.2.2  skrll  * All rights reserved.
      5  1.4.2.2  skrll  *
      6  1.4.2.2  skrll  * Copyright (c) 2007 KIYOHARA Takashi
      7  1.4.2.2  skrll  * All rights reserved.
      8  1.4.2.2  skrll  *
      9  1.4.2.2  skrll  * Redistribution and use in source and binary forms, with or without
     10  1.4.2.2  skrll  * modification, are permitted provided that the following conditions
     11  1.4.2.2  skrll  * are met:
     12  1.4.2.2  skrll  * 1. Redistributions of source code must retain the above copyright
     13  1.4.2.2  skrll  *    notice, this list of conditions and the following disclaimer.
     14  1.4.2.2  skrll  * 2. Redistributions in binary form must reproduce the above copyright
     15  1.4.2.2  skrll  *    notice, this list of conditions and the following disclaimer in the
     16  1.4.2.2  skrll  *    documentation and/or other materials provided with the distribution.
     17  1.4.2.2  skrll  *
     18  1.4.2.2  skrll  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
     19  1.4.2.2  skrll  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
     20  1.4.2.2  skrll  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
     21  1.4.2.2  skrll  * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
     22  1.4.2.2  skrll  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
     23  1.4.2.2  skrll  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
     24  1.4.2.2  skrll  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     25  1.4.2.2  skrll  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
     26  1.4.2.2  skrll  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
     27  1.4.2.2  skrll  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     28  1.4.2.2  skrll  * POSSIBILITY OF SUCH DAMAGE.
     29  1.4.2.2  skrll  */
     30  1.4.2.2  skrll 
     31  1.4.2.2  skrll #include <sys/cdefs.h>
     32  1.4.2.2  skrll __KERNEL_RCSID(0, "$NetBSD: bth5.c,v 1.4.2.2 2017/08/28 17:52:01 skrll Exp $");
     33  1.4.2.2  skrll 
     34  1.4.2.2  skrll #include <sys/types.h>
     35  1.4.2.2  skrll #include <sys/param.h>
     36  1.4.2.2  skrll #include <sys/callout.h>
     37  1.4.2.2  skrll #include <sys/conf.h>
     38  1.4.2.2  skrll #include <sys/device.h>
     39  1.4.2.2  skrll #include <sys/errno.h>
     40  1.4.2.2  skrll #include <sys/fcntl.h>
     41  1.4.2.2  skrll #include <sys/kauth.h>
     42  1.4.2.2  skrll #include <sys/kernel.h>
     43  1.4.2.2  skrll #include <sys/malloc.h>
     44  1.4.2.2  skrll #include <sys/mbuf.h>
     45  1.4.2.2  skrll #include <sys/proc.h>
     46  1.4.2.2  skrll #include <sys/sysctl.h>
     47  1.4.2.2  skrll #include <sys/syslimits.h>
     48  1.4.2.2  skrll #include <sys/systm.h>
     49  1.4.2.2  skrll #include <sys/tty.h>
     50  1.4.2.2  skrll 
     51  1.4.2.2  skrll #include <netbt/bluetooth.h>
     52  1.4.2.2  skrll #include <netbt/hci.h>
     53  1.4.2.2  skrll 
     54  1.4.2.2  skrll #include <dev/bluetooth/bth5.h>
     55  1.4.2.2  skrll 
     56  1.4.2.2  skrll #include "ioconf.h"
     57  1.4.2.2  skrll 
     58  1.4.2.2  skrll #ifdef BTH5_DEBUG
     59  1.4.2.2  skrll #ifdef DPRINTF
     60  1.4.2.2  skrll #undef DPRINTF
     61  1.4.2.2  skrll #endif
     62  1.4.2.2  skrll #ifdef DPRINTFN
     63  1.4.2.2  skrll #undef DPRINTFN
     64  1.4.2.2  skrll #endif
     65  1.4.2.2  skrll 
     66  1.4.2.2  skrll #define DPRINTF(x)	printf x
     67  1.4.2.2  skrll #define DPRINTFN(n, x)	do { if (bth5_debug > (n)) printf x; } while (0)
     68  1.4.2.2  skrll int bth5_debug = 3;
     69  1.4.2.2  skrll #else
     70  1.4.2.2  skrll #undef DPRINTF
     71  1.4.2.2  skrll #undef DPRINTFN
     72  1.4.2.2  skrll 
     73  1.4.2.2  skrll #define DPRINTF(x)
     74  1.4.2.2  skrll #define DPRINTFN(n, x)
     75  1.4.2.2  skrll #endif
     76  1.4.2.2  skrll 
     77  1.4.2.2  skrll struct bth5_softc {
     78  1.4.2.2  skrll 	device_t sc_dev;
     79  1.4.2.2  skrll 
     80  1.4.2.2  skrll 	struct tty *sc_tp;
     81  1.4.2.2  skrll 	struct hci_unit *sc_unit;		/* Bluetooth HCI Unit */
     82  1.4.2.2  skrll 	struct bt_stats sc_stats;
     83  1.4.2.2  skrll 
     84  1.4.2.2  skrll 	int sc_flags;
     85  1.4.2.2  skrll 
     86  1.4.2.2  skrll 	/* output queues */
     87  1.4.2.2  skrll 	MBUFQ_HEAD()	sc_cmdq;
     88  1.4.2.2  skrll 	MBUFQ_HEAD()	sc_aclq;
     89  1.4.2.2  skrll 	MBUFQ_HEAD()	sc_scoq;
     90  1.4.2.2  skrll 
     91  1.4.2.2  skrll 	int sc_baud;
     92  1.4.2.2  skrll 	int sc_init_baud;
     93  1.4.2.2  skrll 
     94  1.4.2.2  skrll 	/* variables of SLIP Layer */
     95  1.4.2.2  skrll 	struct mbuf *sc_txp;			/* outgoing packet */
     96  1.4.2.2  skrll 	struct mbuf *sc_rxp;			/* incoming packet */
     97  1.4.2.2  skrll 	int sc_slip_txrsv;			/* reserved byte data */
     98  1.4.2.2  skrll 	int sc_slip_rxexp;			/* expected byte data */
     99  1.4.2.2  skrll 	void (*sc_transmit_callback)(struct bth5_softc *, struct mbuf *);
    100  1.4.2.2  skrll 
    101  1.4.2.2  skrll 	/* variables of Packet Integrity Layer */
    102  1.4.2.2  skrll 	int sc_pi_txcrc;			/* use CRC, if true */
    103  1.4.2.2  skrll 
    104  1.4.2.2  skrll 	/* variables of MUX Layer */
    105  1.4.2.2  skrll 	bool sc_mux_send_ack;			/* flag for send_ack */
    106  1.4.2.2  skrll 	bool sc_mux_choke;			/* Choke signal */
    107  1.4.2.2  skrll 	struct timeval sc_mux_lastrx;		/* Last Rx Pkt Time */
    108  1.4.2.2  skrll 
    109  1.4.2.2  skrll 	/* variables of Sequencing Layer */
    110  1.4.2.2  skrll 	MBUFQ_HEAD() sc_seqq;			/* Sequencing Layer queue */
    111  1.4.2.2  skrll 	MBUFQ_HEAD() sc_seq_retryq;		/* retry queue */
    112  1.4.2.2  skrll 	uint32_t sc_seq_txseq;
    113  1.4.2.2  skrll 	uint32_t sc_seq_txack;
    114  1.4.2.2  skrll 	uint32_t sc_seq_expected_rxseq;
    115  1.4.2.2  skrll 	uint32_t sc_seq_winspace;
    116  1.4.2.2  skrll 	uint32_t sc_seq_retries;
    117  1.4.2.2  skrll 	callout_t sc_seq_timer;
    118  1.4.2.2  skrll 	uint32_t sc_seq_timeout;
    119  1.4.2.2  skrll 	uint32_t sc_seq_winsize;
    120  1.4.2.2  skrll 	uint32_t sc_seq_retry_limit;
    121  1.4.2.2  skrll 
    122  1.4.2.2  skrll 	/* variables of Datagram Queue Layer */
    123  1.4.2.2  skrll 	MBUFQ_HEAD() sc_dgq;			/* Datagram Queue Layer queue */
    124  1.4.2.2  skrll 
    125  1.4.2.2  skrll 	/* variables of BTH5 Link Establishment Protocol */
    126  1.4.2.2  skrll 	bool sc_le_muzzled;
    127  1.4.2.2  skrll 	bth5_le_state_t sc_le_state;
    128  1.4.2.2  skrll 	callout_t sc_le_timer;
    129  1.4.2.2  skrll 
    130  1.4.2.2  skrll 	struct sysctllog *sc_log;		/* sysctl log */
    131  1.4.2.2  skrll };
    132  1.4.2.2  skrll 
    133  1.4.2.2  skrll /* sc_flags */
    134  1.4.2.2  skrll #define	BTH5_XMIT	(1 << 0)	/* transmit active */
    135  1.4.2.2  skrll #define	BTH5_ENABLED	(1 << 1)	/* is enabled */
    136  1.4.2.2  skrll 
    137  1.4.2.2  skrll static int bthfive_match(device_t, cfdata_t, void *);
    138  1.4.2.2  skrll static void bthfive_attach(device_t, device_t, void *);
    139  1.4.2.2  skrll static int bthfive_detach(device_t, int);
    140  1.4.2.2  skrll 
    141  1.4.2.2  skrll /* tty functions */
    142  1.4.2.2  skrll static int bth5open(dev_t, struct tty *);
    143  1.4.2.2  skrll static int bth5close(struct tty *, int);
    144  1.4.2.2  skrll static int bth5ioctl(struct tty *, u_long, void *, int, struct lwp *);
    145  1.4.2.2  skrll 
    146  1.4.2.2  skrll static int bth5_slip_transmit(struct tty *);
    147  1.4.2.2  skrll static int bth5_slip_receive(int, struct tty *);
    148  1.4.2.2  skrll 
    149  1.4.2.2  skrll static void bth5_pktintegrity_transmit(struct bth5_softc *);
    150  1.4.2.2  skrll static void bth5_pktintegrity_receive(struct bth5_softc *, struct mbuf *);
    151  1.4.2.2  skrll static void bth5_crc_update(uint16_t *, uint8_t);
    152  1.4.2.2  skrll static uint16_t bth5_crc_reverse(uint16_t);
    153  1.4.2.2  skrll 
    154  1.4.2.2  skrll static void bth5_mux_transmit(struct bth5_softc *sc);
    155  1.4.2.2  skrll static void bth5_mux_receive(struct bth5_softc *sc, struct mbuf *m);
    156  1.4.2.2  skrll static __inline void bth5_send_ack_command(struct bth5_softc *sc);
    157  1.4.2.2  skrll static __inline struct mbuf *bth5_create_ackpkt(void);
    158  1.4.2.2  skrll static __inline void bth5_set_choke(struct bth5_softc *, bool);
    159  1.4.2.2  skrll 
    160  1.4.2.2  skrll static void bth5_sequencing_receive(struct bth5_softc *, struct mbuf *);
    161  1.4.2.2  skrll static bool bth5_tx_reliable_pkt(struct bth5_softc *, struct mbuf *, u_int);
    162  1.4.2.2  skrll static __inline u_int bth5_get_txack(struct bth5_softc *);
    163  1.4.2.2  skrll static void bth5_signal_rxack(struct bth5_softc *, uint32_t);
    164  1.4.2.2  skrll static void bth5_reliabletx_callback(struct bth5_softc *, struct mbuf *);
    165  1.4.2.2  skrll static void bth5_timer_timeout(void *);
    166  1.4.2.2  skrll static void bth5_sequencing_reset(struct bth5_softc *);
    167  1.4.2.2  skrll 
    168  1.4.2.2  skrll static void bth5_datagramq_receive(struct bth5_softc *, struct mbuf *);
    169  1.4.2.2  skrll static bool bth5_tx_unreliable_pkt(struct bth5_softc *, struct mbuf *, u_int);
    170  1.4.2.2  skrll static void bth5_unreliabletx_callback(struct bth5_softc *, struct mbuf *);
    171  1.4.2.2  skrll 
    172  1.4.2.2  skrll static int bth5_start_le(struct bth5_softc *);
    173  1.4.2.2  skrll static void bth5_terminate_le(struct bth5_softc *);
    174  1.4.2.2  skrll static void bth5_input_le(struct bth5_softc *, struct mbuf *);
    175  1.4.2.2  skrll static void bth5_le_timeout(void *);
    176  1.4.2.2  skrll 
    177  1.4.2.2  skrll static void bth5_start(struct bth5_softc *);
    178  1.4.2.2  skrll 
    179  1.4.2.2  skrll /* bluetooth hci functions */
    180  1.4.2.2  skrll static int bth5_enable(device_t);
    181  1.4.2.2  skrll static void bth5_disable(device_t);
    182  1.4.2.2  skrll static void bth5_output_cmd(device_t, struct mbuf *);
    183  1.4.2.2  skrll static void bth5_output_acl(device_t, struct mbuf *);
    184  1.4.2.2  skrll static void bth5_output_sco(device_t, struct mbuf *);
    185  1.4.2.2  skrll static void bth5_stats(device_t, struct bt_stats *, int);
    186  1.4.2.2  skrll 
    187  1.4.2.2  skrll #ifdef BTH5_DEBUG
    188  1.4.2.2  skrll static void bth5_packet_print(struct mbuf *m);
    189  1.4.2.2  skrll #endif
    190  1.4.2.2  skrll 
    191  1.4.2.2  skrll 
    192  1.4.2.2  skrll /*
    193  1.4.2.2  skrll  * It doesn't need to be exported, as only bth5attach() uses it,
    194  1.4.2.2  skrll  * but there's no "official" way to make it static.
    195  1.4.2.2  skrll  */
    196  1.4.2.2  skrll CFATTACH_DECL_NEW(bthfive, sizeof(struct bth5_softc),
    197  1.4.2.2  skrll     bthfive_match, bthfive_attach, bthfive_detach, NULL);
    198  1.4.2.2  skrll 
    199  1.4.2.2  skrll static struct linesw bth5_disc = {
    200  1.4.2.2  skrll 	.l_name = "bth5",
    201  1.4.2.2  skrll 	.l_open = bth5open,
    202  1.4.2.2  skrll 	.l_close = bth5close,
    203  1.4.2.2  skrll 	.l_read = ttyerrio,
    204  1.4.2.2  skrll 	.l_write = ttyerrio,
    205  1.4.2.2  skrll 	.l_ioctl = bth5ioctl,
    206  1.4.2.2  skrll 	.l_rint = bth5_slip_receive,
    207  1.4.2.2  skrll 	.l_start = bth5_slip_transmit,
    208  1.4.2.2  skrll 	.l_modem = ttymodem,
    209  1.4.2.2  skrll 	.l_poll = ttyerrpoll
    210  1.4.2.2  skrll };
    211  1.4.2.2  skrll 
    212  1.4.2.2  skrll static const struct hci_if bth5_hci = {
    213  1.4.2.2  skrll 	.enable = bth5_enable,
    214  1.4.2.2  skrll 	.disable = bth5_disable,
    215  1.4.2.2  skrll 	.output_cmd = bth5_output_cmd,
    216  1.4.2.2  skrll 	.output_acl = bth5_output_acl,
    217  1.4.2.2  skrll 	.output_sco = bth5_output_sco,
    218  1.4.2.2  skrll 	.get_stats = bth5_stats,
    219  1.4.2.2  skrll 	.ipl = IPL_TTY,
    220  1.4.2.2  skrll };
    221  1.4.2.2  skrll 
    222  1.4.2.2  skrll /* ARGSUSED */
    223  1.4.2.2  skrll void
    224  1.4.2.2  skrll bthfiveattach(int num __unused)
    225  1.4.2.2  skrll {
    226  1.4.2.2  skrll 	int error;
    227  1.4.2.2  skrll 
    228  1.4.2.2  skrll 	error = ttyldisc_attach(&bth5_disc);
    229  1.4.2.2  skrll 	if (error) {
    230  1.4.2.2  skrll 		aprint_error("%s: unable to register line discipline, "
    231  1.4.2.2  skrll 		    "error = %d\n", bthfive_cd.cd_name, error);
    232  1.4.2.2  skrll 		return;
    233  1.4.2.2  skrll 	}
    234  1.4.2.2  skrll 
    235  1.4.2.2  skrll 	error = config_cfattach_attach(bthfive_cd.cd_name, &bthfive_ca);
    236  1.4.2.2  skrll 	if (error) {
    237  1.4.2.2  skrll 		aprint_error("%s: unable to register cfattach, error = %d\n",
    238  1.4.2.2  skrll 		    bthfive_cd.cd_name, error);
    239  1.4.2.2  skrll 		config_cfdriver_detach(&bthfive_cd);
    240  1.4.2.2  skrll 		(void) ttyldisc_detach(&bth5_disc);
    241  1.4.2.2  skrll 	}
    242  1.4.2.2  skrll }
    243  1.4.2.2  skrll 
    244  1.4.2.2  skrll /*
    245  1.4.2.2  skrll  * Autoconf match routine.
    246  1.4.2.2  skrll  *
    247  1.4.2.2  skrll  * XXX: unused: config_attach_pseudo(9) does not call ca_match.
    248  1.4.2.2  skrll  */
    249  1.4.2.2  skrll /* ARGSUSED */
    250  1.4.2.2  skrll static int
    251  1.4.2.2  skrll bthfive_match(device_t self __unused, cfdata_t cfdata __unused,
    252  1.4.2.2  skrll 	   void *arg __unused)
    253  1.4.2.2  skrll {
    254  1.4.2.2  skrll 
    255  1.4.2.2  skrll 	/* pseudo-device; always present */
    256  1.4.2.2  skrll 	return 1;
    257  1.4.2.2  skrll }
    258  1.4.2.2  skrll 
    259  1.4.2.2  skrll /*
    260  1.4.2.2  skrll  * Autoconf attach routine.  Called by config_attach_pseudo(9) when we
    261  1.4.2.2  skrll  * open the line discipline.
    262  1.4.2.2  skrll  */
    263  1.4.2.2  skrll /* ARGSUSED */
    264  1.4.2.2  skrll static void
    265  1.4.2.2  skrll bthfive_attach(device_t parent __unused, device_t self, void *aux __unused)
    266  1.4.2.2  skrll {
    267  1.4.2.2  skrll 	struct bth5_softc *sc = device_private(self);
    268  1.4.2.2  skrll 	const struct sysctlnode *node;
    269  1.4.2.2  skrll 	int rc, bth5_node_num;
    270  1.4.2.2  skrll 
    271  1.4.2.2  skrll 	aprint_normal("\n");
    272  1.4.2.2  skrll 	aprint_naive("\n");
    273  1.4.2.2  skrll 
    274  1.4.2.2  skrll 	sc->sc_dev = self;
    275  1.4.2.2  skrll 	callout_init(&sc->sc_seq_timer, 0);
    276  1.4.2.2  skrll 	callout_setfunc(&sc->sc_seq_timer, bth5_timer_timeout, sc);
    277  1.4.2.2  skrll 	callout_init(&sc->sc_le_timer, 0);
    278  1.4.2.2  skrll 	callout_setfunc(&sc->sc_le_timer, bth5_le_timeout, sc);
    279  1.4.2.2  skrll 	sc->sc_seq_timeout = BTH5_SEQ_TX_TIMEOUT;
    280  1.4.2.2  skrll 	sc->sc_seq_winsize = BTH5_SEQ_TX_WINSIZE;
    281  1.4.2.2  skrll 	sc->sc_seq_retry_limit = BTH5_SEQ_TX_RETRY_LIMIT;
    282  1.4.2.2  skrll 	MBUFQ_INIT(&sc->sc_seqq);
    283  1.4.2.2  skrll 	MBUFQ_INIT(&sc->sc_seq_retryq);
    284  1.4.2.2  skrll 	MBUFQ_INIT(&sc->sc_dgq);
    285  1.4.2.2  skrll 	MBUFQ_INIT(&sc->sc_cmdq);
    286  1.4.2.2  skrll 	MBUFQ_INIT(&sc->sc_aclq);
    287  1.4.2.2  skrll 	MBUFQ_INIT(&sc->sc_scoq);
    288  1.4.2.2  skrll 
    289  1.4.2.2  skrll 	/* Attach Bluetooth unit */
    290  1.4.2.2  skrll 	sc->sc_unit = hci_attach_pcb(&bth5_hci, self, 0);
    291  1.4.2.2  skrll 
    292  1.4.2.2  skrll 	if ((rc = sysctl_createv(&sc->sc_log, 0, NULL, &node,
    293  1.4.2.2  skrll 	    0, CTLTYPE_NODE, device_xname(self),
    294  1.4.2.2  skrll 	    SYSCTL_DESCR("bth5 controls"),
    295  1.4.2.2  skrll 	    NULL, 0, NULL, 0, CTL_HW, CTL_CREATE, CTL_EOL)) != 0) {
    296  1.4.2.2  skrll 		goto err;
    297  1.4.2.2  skrll 	}
    298  1.4.2.2  skrll 	bth5_node_num = node->sysctl_num;
    299  1.4.2.2  skrll 	if ((rc = sysctl_createv(&sc->sc_log, 0, NULL, &node,
    300  1.4.2.2  skrll 	    CTLFLAG_READWRITE, CTLTYPE_BOOL,
    301  1.4.2.2  skrll 	    "muzzled", SYSCTL_DESCR("muzzled for Link-establishment Layer"),
    302  1.4.2.2  skrll 	    NULL, 0, &sc->sc_le_muzzled,
    303  1.4.2.2  skrll 	    0, CTL_HW, bth5_node_num, CTL_CREATE, CTL_EOL)) != 0) {
    304  1.4.2.2  skrll 		goto err;
    305  1.4.2.2  skrll 	}
    306  1.4.2.2  skrll 	if ((rc = sysctl_createv(&sc->sc_log, 0, NULL, &node,
    307  1.4.2.2  skrll 	    CTLFLAG_READWRITE, CTLTYPE_INT,
    308  1.4.2.2  skrll 	    "txcrc", SYSCTL_DESCR("txcrc for Packet Integrity Layer"),
    309  1.4.2.2  skrll 	    NULL, 0, &sc->sc_pi_txcrc,
    310  1.4.2.2  skrll 	    0, CTL_HW, bth5_node_num, CTL_CREATE, CTL_EOL)) != 0) {
    311  1.4.2.2  skrll 		goto err;
    312  1.4.2.2  skrll 	}
    313  1.4.2.2  skrll 	if ((rc = sysctl_createv(&sc->sc_log, 0, NULL, &node,
    314  1.4.2.2  skrll 	    CTLFLAG_READWRITE, CTLTYPE_INT,
    315  1.4.2.2  skrll 	    "timeout", SYSCTL_DESCR("timeout for Sequencing Layer"),
    316  1.4.2.2  skrll 	    NULL, 0, &sc->sc_seq_timeout,
    317  1.4.2.2  skrll 	    0, CTL_HW, bth5_node_num, CTL_CREATE, CTL_EOL)) != 0) {
    318  1.4.2.2  skrll 		goto err;
    319  1.4.2.2  skrll 	}
    320  1.4.2.2  skrll 	if ((rc = sysctl_createv(&sc->sc_log, 0, NULL, &node,
    321  1.4.2.2  skrll 	    CTLFLAG_READWRITE, CTLTYPE_INT,
    322  1.4.2.2  skrll 	    "winsize", SYSCTL_DESCR("winsize for Sequencing Layer"),
    323  1.4.2.2  skrll 	    NULL, 0, &sc->sc_seq_winsize,
    324  1.4.2.2  skrll 	    0, CTL_HW, bth5_node_num, CTL_CREATE, CTL_EOL)) != 0) {
    325  1.4.2.2  skrll 		goto err;
    326  1.4.2.2  skrll 	}
    327  1.4.2.2  skrll 	if ((rc = sysctl_createv(&sc->sc_log, 0, NULL, &node,
    328  1.4.2.2  skrll 	    CTLFLAG_READWRITE, CTLTYPE_INT,
    329  1.4.2.2  skrll 	    "retry_limit", SYSCTL_DESCR("retry limit for Sequencing Layer"),
    330  1.4.2.2  skrll 	    NULL, 0, &sc->sc_seq_retry_limit,
    331  1.4.2.2  skrll 	    0, CTL_HW, bth5_node_num, CTL_CREATE, CTL_EOL)) != 0) {
    332  1.4.2.2  skrll 		goto err;
    333  1.4.2.2  skrll 	}
    334  1.4.2.2  skrll 	return;
    335  1.4.2.2  skrll 
    336  1.4.2.2  skrll err:
    337  1.4.2.2  skrll 	aprint_error_dev(self, "sysctl_createv failed (rc = %d)\n", rc);
    338  1.4.2.2  skrll }
    339  1.4.2.2  skrll 
    340  1.4.2.2  skrll /*
    341  1.4.2.2  skrll  * Autoconf detach routine.  Called when we close the line discipline.
    342  1.4.2.2  skrll  */
    343  1.4.2.2  skrll /* ARGSUSED */
    344  1.4.2.2  skrll static int
    345  1.4.2.2  skrll bthfive_detach(device_t self, int flags __unused)
    346  1.4.2.2  skrll {
    347  1.4.2.2  skrll 	struct bth5_softc *sc = device_private(self);
    348  1.4.2.2  skrll 
    349  1.4.2.2  skrll 	if (sc->sc_unit != NULL) {
    350  1.4.2.2  skrll 		hci_detach_pcb(sc->sc_unit);
    351  1.4.2.2  skrll 		sc->sc_unit = NULL;
    352  1.4.2.2  skrll 	}
    353  1.4.2.2  skrll 
    354  1.4.2.2  skrll 	callout_halt(&sc->sc_seq_timer, NULL);
    355  1.4.2.2  skrll 	callout_destroy(&sc->sc_seq_timer);
    356  1.4.2.2  skrll 
    357  1.4.2.2  skrll 	callout_halt(&sc->sc_le_timer, NULL);
    358  1.4.2.2  skrll 	callout_destroy(&sc->sc_le_timer);
    359  1.4.2.2  skrll 
    360  1.4.2.2  skrll 	return 0;
    361  1.4.2.2  skrll }
    362  1.4.2.2  skrll 
    363  1.4.2.2  skrll 
    364  1.4.2.2  skrll /*
    365  1.4.2.2  skrll  * Line discipline functions.
    366  1.4.2.2  skrll  */
    367  1.4.2.2  skrll /* ARGSUSED */
    368  1.4.2.2  skrll static int
    369  1.4.2.2  skrll bth5open(dev_t device __unused, struct tty *tp)
    370  1.4.2.2  skrll {
    371  1.4.2.2  skrll 	struct bth5_softc *sc;
    372  1.4.2.2  skrll 	device_t dev;
    373  1.4.2.2  skrll 	cfdata_t cfdata;
    374  1.4.2.2  skrll 	struct lwp *l = curlwp;		/* XXX */
    375  1.4.2.2  skrll 	int error, unit, s;
    376  1.4.2.2  skrll 	static char name[] = "bthfive";
    377  1.4.2.2  skrll 
    378  1.4.2.2  skrll 	error = kauth_authorize_device(l->l_cred, KAUTH_DEVICE_BLUETOOTH_BCSP,
    379  1.4.2.2  skrll 	    KAUTH_ARG(KAUTH_REQ_DEVICE_BLUETOOTH_BCSP_ADD), NULL, NULL, NULL);
    380  1.4.2.2  skrll 	if (error)
    381  1.4.2.2  skrll 		return (error);
    382  1.4.2.2  skrll 
    383  1.4.2.2  skrll 	s = spltty();
    384  1.4.2.2  skrll 
    385  1.4.2.2  skrll 	if (tp->t_linesw == &bth5_disc) {
    386  1.4.2.2  skrll 		sc = tp->t_sc;
    387  1.4.2.2  skrll 		if (sc != NULL) {
    388  1.4.2.2  skrll 			splx(s);
    389  1.4.2.2  skrll 			return EBUSY;
    390  1.4.2.2  skrll 		}
    391  1.4.2.2  skrll 	}
    392  1.4.2.2  skrll 
    393  1.4.2.2  skrll 	KASSERT(tp->t_oproc != NULL);
    394  1.4.2.2  skrll 
    395  1.4.2.2  skrll 	cfdata = malloc(sizeof(struct cfdata), M_DEVBUF, M_WAITOK);
    396  1.4.2.2  skrll 	for (unit = 0; unit < bthfive_cd.cd_ndevs; unit++)
    397  1.4.2.2  skrll 		if (device_lookup(&bthfive_cd, unit) == NULL)
    398  1.4.2.2  skrll 			break;
    399  1.4.2.2  skrll 	cfdata->cf_name = name;
    400  1.4.2.2  skrll 	cfdata->cf_atname = name;
    401  1.4.2.2  skrll 	cfdata->cf_unit = unit;
    402  1.4.2.2  skrll 	cfdata->cf_fstate = FSTATE_STAR;
    403  1.4.2.2  skrll 
    404  1.4.2.2  skrll 	aprint_normal("%s%d at tty major %llu minor %llu",
    405  1.4.2.2  skrll 	    name, unit, (unsigned long long)major(tp->t_dev),
    406  1.4.2.2  skrll 	    (unsigned long long)minor(tp->t_dev));
    407  1.4.2.2  skrll 	dev = config_attach_pseudo(cfdata);
    408  1.4.2.2  skrll 	if (dev == NULL) {
    409  1.4.2.2  skrll 		splx(s);
    410  1.4.2.2  skrll 		return EIO;
    411  1.4.2.2  skrll 	}
    412  1.4.2.2  skrll 	sc = device_private(dev);
    413  1.4.2.2  skrll 
    414  1.4.2.2  skrll 	mutex_spin_enter(&tty_lock);
    415  1.4.2.2  skrll 	tp->t_sc = sc;
    416  1.4.2.2  skrll 	sc->sc_tp = tp;
    417  1.4.2.2  skrll 	ttyflush(tp, FREAD | FWRITE);
    418  1.4.2.2  skrll 	mutex_spin_exit(&tty_lock);
    419  1.4.2.2  skrll 
    420  1.4.2.2  skrll 	splx(s);
    421  1.4.2.2  skrll 
    422  1.4.2.2  skrll 	sc->sc_slip_txrsv = BTH5_SLIP_PKTSTART;
    423  1.4.2.2  skrll 	bth5_sequencing_reset(sc);
    424  1.4.2.2  skrll 
    425  1.4.2.2  skrll 	/* start link-establishment */
    426  1.4.2.2  skrll 	bth5_start_le(sc);
    427  1.4.2.2  skrll 
    428  1.4.2.2  skrll 	return 0;
    429  1.4.2.2  skrll }
    430  1.4.2.2  skrll 
    431  1.4.2.2  skrll /* ARGSUSED */
    432  1.4.2.2  skrll static int
    433  1.4.2.2  skrll bth5close(struct tty *tp, int flag __unused)
    434  1.4.2.2  skrll {
    435  1.4.2.2  skrll 	struct bth5_softc *sc = tp->t_sc;
    436  1.4.2.2  skrll 	cfdata_t cfdata;
    437  1.4.2.2  skrll 	int s;
    438  1.4.2.2  skrll 
    439  1.4.2.2  skrll 	/* terminate link-establishment */
    440  1.4.2.2  skrll 	bth5_terminate_le(sc);
    441  1.4.2.2  skrll 
    442  1.4.2.2  skrll 	s = spltty();
    443  1.4.2.2  skrll 
    444  1.4.2.2  skrll 	MBUFQ_DRAIN(&sc->sc_dgq);
    445  1.4.2.2  skrll 	bth5_sequencing_reset(sc);
    446  1.4.2.2  skrll 
    447  1.4.2.2  skrll 	mutex_spin_enter(&tty_lock);
    448  1.4.2.2  skrll 	ttyflush(tp, FREAD | FWRITE);
    449  1.4.2.2  skrll 	mutex_spin_exit(&tty_lock);	/* XXX */
    450  1.4.2.2  skrll 	ttyldisc_release(tp->t_linesw);
    451  1.4.2.2  skrll 	tp->t_linesw = ttyldisc_default();
    452  1.4.2.2  skrll 	if (sc != NULL) {
    453  1.4.2.2  skrll 		tp->t_sc = NULL;
    454  1.4.2.2  skrll 		if (sc->sc_tp == tp) {
    455  1.4.2.2  skrll 			cfdata = device_cfdata(sc->sc_dev);
    456  1.4.2.2  skrll 			config_detach(sc->sc_dev, 0);
    457  1.4.2.2  skrll 			free(cfdata, M_DEVBUF);
    458  1.4.2.2  skrll 		}
    459  1.4.2.2  skrll 
    460  1.4.2.2  skrll 	}
    461  1.4.2.2  skrll 	splx(s);
    462  1.4.2.2  skrll 	return 0;
    463  1.4.2.2  skrll }
    464  1.4.2.2  skrll 
    465  1.4.2.2  skrll /* ARGSUSED */
    466  1.4.2.2  skrll static int
    467  1.4.2.2  skrll bth5ioctl(struct tty *tp, u_long cmd, void *data, int flag __unused,
    468  1.4.2.2  skrll 	  struct lwp *l __unused)
    469  1.4.2.2  skrll {
    470  1.4.2.2  skrll 	struct bth5_softc *sc = tp->t_sc;
    471  1.4.2.2  skrll 	int error;
    472  1.4.2.2  skrll 
    473  1.4.2.2  skrll 	if (sc == NULL || tp != sc->sc_tp)
    474  1.4.2.2  skrll 		return EPASSTHROUGH;
    475  1.4.2.2  skrll 
    476  1.4.2.2  skrll 	error = 0;
    477  1.4.2.2  skrll 	switch (cmd) {
    478  1.4.2.2  skrll 	default:
    479  1.4.2.2  skrll 		error = EPASSTHROUGH;
    480  1.4.2.2  skrll 		break;
    481  1.4.2.2  skrll 	}
    482  1.4.2.2  skrll 
    483  1.4.2.2  skrll 	return error;
    484  1.4.2.2  skrll }
    485  1.4.2.2  skrll 
    486  1.4.2.2  skrll 
    487  1.4.2.2  skrll /*
    488  1.4.2.2  skrll  * UART Driver Layer is supported by com-driver.
    489  1.4.2.2  skrll  */
    490  1.4.2.2  skrll 
    491  1.4.2.2  skrll /*
    492  1.4.2.2  skrll  * BTH5 SLIP Layer functions:
    493  1.4.2.2  skrll  *   Supports to transmit/receive a byte stream.
    494  1.4.2.2  skrll  *   SLIP protocol described in Internet standard RFC 1055.
    495  1.4.2.2  skrll  */
    496  1.4.2.2  skrll static int
    497  1.4.2.2  skrll bth5_slip_transmit(struct tty *tp)
    498  1.4.2.2  skrll {
    499  1.4.2.2  skrll 	struct bth5_softc *sc = tp->t_sc;
    500  1.4.2.2  skrll 	struct mbuf *m;
    501  1.4.2.2  skrll 	int count, rlen;
    502  1.4.2.2  skrll 	uint8_t *rptr;
    503  1.4.2.2  skrll 
    504  1.4.2.2  skrll 	m = sc->sc_txp;
    505  1.4.2.2  skrll 	if (m == NULL) {
    506  1.4.2.2  skrll 		sc->sc_flags &= ~BTH5_XMIT;
    507  1.4.2.2  skrll 		bth5_mux_transmit(sc);
    508  1.4.2.2  skrll 		return 0;
    509  1.4.2.2  skrll 	}
    510  1.4.2.2  skrll 
    511  1.4.2.2  skrll 	count = 0;
    512  1.4.2.2  skrll 	rlen = 0;
    513  1.4.2.2  skrll 	rptr = mtod(m, uint8_t *);
    514  1.4.2.2  skrll 
    515  1.4.2.2  skrll 	if (sc->sc_slip_txrsv != 0) {
    516  1.4.2.2  skrll #ifdef BTH5_DEBUG
    517  1.4.2.2  skrll 		if (sc->sc_slip_txrsv == BTH5_SLIP_PKTSTART)
    518  1.4.2.2  skrll 			DPRINTFN(4, ("%s: slip transmit start\n",
    519  1.4.2.2  skrll 			    device_xname(sc->sc_dev)));
    520  1.4.2.2  skrll 		else
    521  1.4.2.2  skrll 			DPRINTFN(4, ("0x%02x ", sc->sc_slip_txrsv));
    522  1.4.2.2  skrll #endif
    523  1.4.2.2  skrll 
    524  1.4.2.2  skrll 		if (putc(sc->sc_slip_txrsv, &tp->t_outq) < 0)
    525  1.4.2.2  skrll 			return 0;
    526  1.4.2.2  skrll 		count++;
    527  1.4.2.2  skrll 
    528  1.4.2.2  skrll 		if (sc->sc_slip_txrsv == BTH5_SLIP_ESCAPE_PKTEND ||
    529  1.4.2.2  skrll 		    sc->sc_slip_txrsv == BTH5_SLIP_ESCAPE_XON ||
    530  1.4.2.2  skrll 		    sc->sc_slip_txrsv == BTH5_SLIP_ESCAPE_XOFF ||
    531  1.4.2.2  skrll 		    sc->sc_slip_txrsv == BTH5_SLIP_ESCAPE_ESCAPE) {
    532  1.4.2.2  skrll 			rlen++;
    533  1.4.2.2  skrll 			rptr++;
    534  1.4.2.2  skrll 		}
    535  1.4.2.2  skrll 		sc->sc_slip_txrsv = 0;
    536  1.4.2.2  skrll 	}
    537  1.4.2.2  skrll 
    538  1.4.2.2  skrll 	for(;;) {
    539  1.4.2.2  skrll 		if (rlen >= m->m_len) {
    540  1.4.2.2  skrll 			m = m->m_next;
    541  1.4.2.2  skrll 			if (m == NULL) {
    542  1.4.2.2  skrll 				if (putc(BTH5_SLIP_PKTEND, &tp->t_outq) < 0)
    543  1.4.2.2  skrll 					break;
    544  1.4.2.2  skrll 
    545  1.4.2.2  skrll 				DPRINTFN(4, ("\n%s: slip transmit end\n",
    546  1.4.2.2  skrll 				    device_xname(sc->sc_dev)));
    547  1.4.2.2  skrll 
    548  1.4.2.2  skrll 				m = sc->sc_txp;
    549  1.4.2.2  skrll 				sc->sc_txp = NULL;
    550  1.4.2.2  skrll 				sc->sc_slip_txrsv = BTH5_SLIP_PKTSTART;
    551  1.4.2.2  skrll 
    552  1.4.2.2  skrll 				sc->sc_transmit_callback(sc, m);
    553  1.4.2.2  skrll 				m = NULL;
    554  1.4.2.2  skrll 				break;
    555  1.4.2.2  skrll 			}
    556  1.4.2.2  skrll 
    557  1.4.2.2  skrll 			rlen = 0;
    558  1.4.2.2  skrll 			rptr = mtod(m, uint8_t *);
    559  1.4.2.2  skrll 			continue;
    560  1.4.2.2  skrll 		}
    561  1.4.2.2  skrll 
    562  1.4.2.2  skrll 		if (*rptr == BTH5_SLIP_PKTEND) {
    563  1.4.2.2  skrll 			if (putc(BTH5_SLIP_ESCAPE, &tp->t_outq) < 0)
    564  1.4.2.2  skrll 				break;
    565  1.4.2.2  skrll 			count++;
    566  1.4.2.2  skrll 			DPRINTFN(4, (" esc "));
    567  1.4.2.2  skrll 
    568  1.4.2.2  skrll 			if (putc(BTH5_SLIP_ESCAPE_PKTEND, &tp->t_outq) < 0) {
    569  1.4.2.2  skrll 				sc->sc_slip_txrsv = BTH5_SLIP_ESCAPE_PKTEND;
    570  1.4.2.2  skrll 				break;
    571  1.4.2.2  skrll 			}
    572  1.4.2.2  skrll 			DPRINTFN(4, ("0x%02x ", BTH5_SLIP_ESCAPE_PKTEND));
    573  1.4.2.2  skrll 			rptr++;
    574  1.4.2.2  skrll 		} else if (*rptr == BTH5_SLIP_XON) {
    575  1.4.2.2  skrll 			if (putc(BTH5_SLIP_ESCAPE, &tp->t_outq) < 0)
    576  1.4.2.2  skrll 				break;
    577  1.4.2.2  skrll 			count++;
    578  1.4.2.2  skrll 			DPRINTFN(4, (" esc "));
    579  1.4.2.2  skrll 
    580  1.4.2.2  skrll 			if (putc(BTH5_SLIP_ESCAPE_XON, &tp->t_outq) < 0) {
    581  1.4.2.2  skrll 				sc->sc_slip_txrsv = BTH5_SLIP_ESCAPE_XON;
    582  1.4.2.2  skrll 				break;
    583  1.4.2.2  skrll 			}
    584  1.4.2.2  skrll 			DPRINTFN(4, ("0x%02x ", BTH5_SLIP_ESCAPE_XON));
    585  1.4.2.2  skrll 			rptr++;
    586  1.4.2.2  skrll 		} else if (*rptr == BTH5_SLIP_XOFF) {
    587  1.4.2.2  skrll 			if (putc(BTH5_SLIP_ESCAPE, &tp->t_outq) < 0)
    588  1.4.2.2  skrll 				break;
    589  1.4.2.2  skrll 			count++;
    590  1.4.2.2  skrll 			DPRINTFN(4, (" esc "));
    591  1.4.2.2  skrll 
    592  1.4.2.2  skrll 			if (putc(BTH5_SLIP_ESCAPE_XOFF, &tp->t_outq) < 0) {
    593  1.4.2.2  skrll 				sc->sc_slip_txrsv = BTH5_SLIP_ESCAPE_XOFF;
    594  1.4.2.2  skrll 				break;
    595  1.4.2.2  skrll 			}
    596  1.4.2.2  skrll 			DPRINTFN(4, ("0x%02x ", BTH5_SLIP_ESCAPE_XOFF));
    597  1.4.2.2  skrll 			rptr++;
    598  1.4.2.2  skrll 		} else if (*rptr == BTH5_SLIP_ESCAPE) {
    599  1.4.2.2  skrll 			if (putc(BTH5_SLIP_ESCAPE, &tp->t_outq) < 0)
    600  1.4.2.2  skrll 				break;
    601  1.4.2.2  skrll 			count++;
    602  1.4.2.2  skrll 			DPRINTFN(4, (" esc "));
    603  1.4.2.2  skrll 
    604  1.4.2.2  skrll 			if (putc(BTH5_SLIP_ESCAPE_ESCAPE, &tp->t_outq) < 0) {
    605  1.4.2.2  skrll 				sc->sc_slip_txrsv = BTH5_SLIP_ESCAPE_ESCAPE;
    606  1.4.2.2  skrll 				break;
    607  1.4.2.2  skrll 			}
    608  1.4.2.2  skrll 			DPRINTFN(4, ("0x%02x ", BTH5_SLIP_ESCAPE_ESCAPE));
    609  1.4.2.2  skrll 			rptr++;
    610  1.4.2.2  skrll 		} else {
    611  1.4.2.2  skrll 			if (putc(*rptr++, &tp->t_outq) < 0)
    612  1.4.2.2  skrll 				break;
    613  1.4.2.2  skrll 			DPRINTFN(4, ("0x%02x ", *(rptr - 1)));
    614  1.4.2.2  skrll 		}
    615  1.4.2.2  skrll 		rlen++;
    616  1.4.2.2  skrll 		count++;
    617  1.4.2.2  skrll 	}
    618  1.4.2.2  skrll 	if (m != NULL)
    619  1.4.2.2  skrll 		m_adj(m, rlen);
    620  1.4.2.2  skrll 
    621  1.4.2.2  skrll 	sc->sc_stats.byte_tx += count;
    622  1.4.2.2  skrll 
    623  1.4.2.2  skrll 	if (tp->t_outq.c_cc != 0)
    624  1.4.2.2  skrll 		(*tp->t_oproc)(tp);
    625  1.4.2.2  skrll 
    626  1.4.2.2  skrll 	return 0;
    627  1.4.2.2  skrll }
    628  1.4.2.2  skrll 
    629  1.4.2.2  skrll static int
    630  1.4.2.2  skrll bth5_slip_receive(int c, struct tty *tp)
    631  1.4.2.2  skrll {
    632  1.4.2.2  skrll 	struct bth5_softc *sc = tp->t_sc;
    633  1.4.2.2  skrll 	struct mbuf *m = sc->sc_rxp;
    634  1.4.2.2  skrll 	int discard = 0;
    635  1.4.2.2  skrll 	const char *errstr;
    636  1.4.2.2  skrll 
    637  1.4.2.2  skrll 	c &= TTY_CHARMASK;
    638  1.4.2.2  skrll 
    639  1.4.2.2  skrll 	/* If we already started a packet, find the trailing end of it. */
    640  1.4.2.2  skrll 	if (m) {
    641  1.4.2.2  skrll 		while (m->m_next)
    642  1.4.2.2  skrll 			m = m->m_next;
    643  1.4.2.2  skrll 
    644  1.4.2.2  skrll 		if (M_TRAILINGSPACE(m) == 0) {
    645  1.4.2.2  skrll 			/* extend mbuf */
    646  1.4.2.2  skrll 			MGET(m->m_next, M_DONTWAIT, MT_DATA);
    647  1.4.2.2  skrll 			if (m->m_next == NULL) {
    648  1.4.2.2  skrll 				aprint_error_dev(sc->sc_dev,
    649  1.4.2.2  skrll 				    "out of memory\n");
    650  1.4.2.2  skrll 				sc->sc_stats.err_rx++;
    651  1.4.2.2  skrll 				return 0;	/* (lost sync) */
    652  1.4.2.2  skrll 			}
    653  1.4.2.2  skrll 
    654  1.4.2.2  skrll 			m = m->m_next;
    655  1.4.2.2  skrll 			m->m_len = 0;
    656  1.4.2.2  skrll 		}
    657  1.4.2.2  skrll 	} else
    658  1.4.2.2  skrll 		if (c != BTH5_SLIP_PKTSTART) {
    659  1.4.2.2  skrll 			discard = 1;
    660  1.4.2.2  skrll 			errstr = "not sync";
    661  1.4.2.2  skrll 			goto discarded;
    662  1.4.2.2  skrll 		}
    663  1.4.2.2  skrll 
    664  1.4.2.2  skrll 	switch (c) {
    665  1.4.2.2  skrll 	case BTH5_SLIP_PKTSTART /* or _PKTEND */:
    666  1.4.2.2  skrll 		if (m == NULL) {
    667  1.4.2.2  skrll 			/* BTH5_SLIP_PKTSTART */
    668  1.4.2.2  skrll 
    669  1.4.2.2  skrll 			DPRINTFN(4, ("%s: slip receive start\n",
    670  1.4.2.2  skrll 			    device_xname(sc->sc_dev)));
    671  1.4.2.2  skrll 
    672  1.4.2.2  skrll 			/* new packet */
    673  1.4.2.2  skrll 			MGETHDR(m, M_DONTWAIT, MT_DATA);
    674  1.4.2.2  skrll 			if (m == NULL) {
    675  1.4.2.2  skrll 				aprint_error_dev(sc->sc_dev,
    676  1.4.2.2  skrll 				    "out of memory\n");
    677  1.4.2.2  skrll 				sc->sc_stats.err_rx++;
    678  1.4.2.2  skrll 				return 0;	/* (lost sync) */
    679  1.4.2.2  skrll 			}
    680  1.4.2.2  skrll 
    681  1.4.2.2  skrll 			sc->sc_rxp = m;
    682  1.4.2.2  skrll 			m->m_pkthdr.len = m->m_len = 0;
    683  1.4.2.2  skrll 			sc->sc_slip_rxexp = 0;
    684  1.4.2.2  skrll 		} else {
    685  1.4.2.2  skrll 			/* BTH5_SLIP_PKTEND */
    686  1.4.2.2  skrll 
    687  1.4.2.2  skrll 			if (m == sc->sc_rxp && m->m_len == 0) {
    688  1.4.2.2  skrll 				DPRINTFN(4, ("%s: resynchronises\n",
    689  1.4.2.2  skrll 				    device_xname(sc->sc_dev)));
    690  1.4.2.2  skrll 
    691  1.4.2.2  skrll 				sc->sc_stats.byte_rx++;
    692  1.4.2.2  skrll 				return 0;
    693  1.4.2.2  skrll 			}
    694  1.4.2.2  skrll 
    695  1.4.2.2  skrll 			DPRINTFN(4, ("%s%s: slip receive end\n",
    696  1.4.2.2  skrll 			    (m->m_len % 16 != 0) ? "\n" :  "",
    697  1.4.2.2  skrll 			    device_xname(sc->sc_dev)));
    698  1.4.2.2  skrll 
    699  1.4.2.2  skrll 			bth5_pktintegrity_receive(sc, sc->sc_rxp);
    700  1.4.2.2  skrll 			sc->sc_rxp = NULL;
    701  1.4.2.2  skrll 			sc->sc_slip_rxexp = BTH5_SLIP_PKTSTART;
    702  1.4.2.2  skrll 		}
    703  1.4.2.2  skrll 		sc->sc_stats.byte_rx++;
    704  1.4.2.2  skrll 		return 0;
    705  1.4.2.2  skrll 
    706  1.4.2.2  skrll 	case BTH5_SLIP_ESCAPE:
    707  1.4.2.2  skrll 
    708  1.4.2.2  skrll 		DPRINTFN(4, ("  esc"));
    709  1.4.2.2  skrll 
    710  1.4.2.2  skrll 		if (sc->sc_slip_rxexp == BTH5_SLIP_ESCAPE) {
    711  1.4.2.2  skrll 			discard = 1;
    712  1.4.2.2  skrll 			errstr = "waiting 0xdc or 0xdb or 0xde of 0xdf";
    713  1.4.2.2  skrll 		} else
    714  1.4.2.2  skrll 			sc->sc_slip_rxexp = BTH5_SLIP_ESCAPE;
    715  1.4.2.2  skrll 		break;
    716  1.4.2.2  skrll 
    717  1.4.2.2  skrll 	default:
    718  1.4.2.2  skrll 		DPRINTFN(4, (" 0x%02x%s",
    719  1.4.2.2  skrll 		    c, (m->m_len % 16 == 15) ? "\n" :  ""));
    720  1.4.2.2  skrll 
    721  1.4.2.2  skrll 		switch (sc->sc_slip_rxexp) {
    722  1.4.2.2  skrll 		case BTH5_SLIP_PKTSTART:
    723  1.4.2.2  skrll 			discard = 1;
    724  1.4.2.2  skrll 			errstr = "waiting 0xc0";
    725  1.4.2.2  skrll 			break;
    726  1.4.2.2  skrll 
    727  1.4.2.2  skrll 		case BTH5_SLIP_ESCAPE:
    728  1.4.2.2  skrll 			if (c == BTH5_SLIP_ESCAPE_PKTEND)
    729  1.4.2.2  skrll 				mtod(m, uint8_t *)[m->m_len++] =
    730  1.4.2.2  skrll 				    BTH5_SLIP_PKTEND;
    731  1.4.2.2  skrll 			else if (c == BTH5_SLIP_ESCAPE_XON)
    732  1.4.2.2  skrll 				mtod(m, uint8_t *)[m->m_len++] =
    733  1.4.2.2  skrll 				    BTH5_SLIP_XON;
    734  1.4.2.2  skrll 			else if (c == BTH5_SLIP_ESCAPE_XOFF)
    735  1.4.2.2  skrll 				mtod(m, uint8_t *)[m->m_len++] =
    736  1.4.2.2  skrll 				    BTH5_SLIP_XOFF;
    737  1.4.2.2  skrll 			else if (c == BTH5_SLIP_ESCAPE_ESCAPE)
    738  1.4.2.2  skrll 				mtod(m, uint8_t *)[m->m_len++] =
    739  1.4.2.2  skrll 				    BTH5_SLIP_ESCAPE;
    740  1.4.2.2  skrll 			else {
    741  1.4.2.2  skrll 				discard = 1;
    742  1.4.2.2  skrll 				errstr = "unknown escape";
    743  1.4.2.2  skrll 			}
    744  1.4.2.2  skrll 			sc->sc_slip_rxexp = 0;
    745  1.4.2.2  skrll 			break;
    746  1.4.2.2  skrll 
    747  1.4.2.2  skrll 		default:
    748  1.4.2.2  skrll 			mtod(m, uint8_t *)[m->m_len++] = c;
    749  1.4.2.2  skrll 		}
    750  1.4.2.2  skrll 		sc->sc_rxp->m_pkthdr.len++;
    751  1.4.2.2  skrll 	}
    752  1.4.2.2  skrll 	if (discard) {
    753  1.4.2.2  skrll discarded:
    754  1.4.2.2  skrll #ifdef BTH5_DEBUG
    755  1.4.2.2  skrll 		DPRINTFN(4, ("%s: receives unexpected byte 0x%02x: %s\n",
    756  1.4.2.2  skrll 		    device_xname(sc->sc_dev), c, errstr));
    757  1.4.2.2  skrll #else
    758  1.4.2.2  skrll 		__USE(errstr);
    759  1.4.2.2  skrll #endif
    760  1.4.2.2  skrll 	}
    761  1.4.2.2  skrll 	sc->sc_stats.byte_rx++;
    762  1.4.2.2  skrll 
    763  1.4.2.2  skrll 	return 0;
    764  1.4.2.2  skrll }
    765  1.4.2.2  skrll 
    766  1.4.2.2  skrll 
    767  1.4.2.2  skrll /*
    768  1.4.2.2  skrll  * BTH5 Packet Integrity Layer functions:
    769  1.4.2.2  skrll  *   handling Payload Length, Checksum, CRC.
    770  1.4.2.2  skrll  */
    771  1.4.2.2  skrll static void
    772  1.4.2.2  skrll bth5_pktintegrity_transmit(struct bth5_softc *sc)
    773  1.4.2.2  skrll {
    774  1.4.2.2  skrll 	struct mbuf *m = sc->sc_txp;
    775  1.4.2.2  skrll 	bth5_hdr_t *hdrp = mtod(m, bth5_hdr_t *);
    776  1.4.2.2  skrll 	int pldlen;
    777  1.4.2.2  skrll 
    778  1.4.2.2  skrll 	DPRINTFN(3, ("%s: pi transmit\n", device_xname(sc->sc_dev)));
    779  1.4.2.2  skrll 
    780  1.4.2.2  skrll 	pldlen = m->m_pkthdr.len - sizeof(bth5_hdr_t);
    781  1.4.2.2  skrll 
    782  1.4.2.2  skrll 	if (sc->sc_pi_txcrc)
    783  1.4.2.2  skrll 		hdrp->flags |= BTH5_FLAGS_CRC_PRESENT;
    784  1.4.2.2  skrll 
    785  1.4.2.2  skrll 	BTH5_SET_PLEN(hdrp, pldlen);
    786  1.4.2.2  skrll 	BTH5_SET_CSUM(hdrp);
    787  1.4.2.2  skrll 
    788  1.4.2.2  skrll 	if (sc->sc_pi_txcrc) {
    789  1.4.2.2  skrll 		struct mbuf *_m;
    790  1.4.2.2  skrll 		int n = 0;
    791  1.4.2.2  skrll 		uint16_t crc = 0xffff;
    792  1.4.2.2  skrll 		uint8_t *buf;
    793  1.4.2.2  skrll 
    794  1.4.2.2  skrll 		for (_m = m; _m != NULL; _m = _m->m_next) {
    795  1.4.2.2  skrll 			buf = mtod(_m, uint8_t *);
    796  1.4.2.2  skrll 			for (n = 0; n < _m->m_len; n++)
    797  1.4.2.2  skrll 				bth5_crc_update(&crc, *(buf + n));
    798  1.4.2.2  skrll 		}
    799  1.4.2.2  skrll 		crc = htobe16(bth5_crc_reverse(crc));
    800  1.4.2.2  skrll 		m_copyback(m, m->m_pkthdr.len, sizeof(crc), &crc);
    801  1.4.2.2  skrll 	}
    802  1.4.2.2  skrll 
    803  1.4.2.2  skrll #ifdef BTH5_DEBUG
    804  1.4.2.2  skrll 	if (bth5_debug == 3)
    805  1.4.2.2  skrll 		bth5_packet_print(m);
    806  1.4.2.2  skrll #endif
    807  1.4.2.2  skrll 
    808  1.4.2.2  skrll 	bth5_slip_transmit(sc->sc_tp);
    809  1.4.2.2  skrll }
    810  1.4.2.2  skrll 
    811  1.4.2.2  skrll static void
    812  1.4.2.2  skrll bth5_pktintegrity_receive(struct bth5_softc *sc, struct mbuf *m)
    813  1.4.2.2  skrll {
    814  1.4.2.2  skrll 	bth5_hdr_t *hdrp = mtod(m, bth5_hdr_t *);
    815  1.4.2.2  skrll 	u_int pldlen;
    816  1.4.2.2  skrll 	int discard = 0;
    817  1.4.2.2  skrll 	uint16_t crc = 0xffff;
    818  1.4.2.2  skrll 	const char *errstr;
    819  1.4.2.2  skrll 
    820  1.4.2.2  skrll 	DPRINTFN(3, ("%s: pi receive\n", device_xname(sc->sc_dev)));
    821  1.4.2.2  skrll #ifdef BTH5_DEBUG
    822  1.4.2.2  skrll 	if (bth5_debug == 4)
    823  1.4.2.2  skrll 		bth5_packet_print(m);
    824  1.4.2.2  skrll #endif
    825  1.4.2.2  skrll 
    826  1.4.2.2  skrll 	KASSERT(m->m_len >= sizeof(bth5_hdr_t));
    827  1.4.2.2  skrll 
    828  1.4.2.2  skrll 	pldlen = m->m_pkthdr.len - sizeof(bth5_hdr_t) -
    829  1.4.2.2  skrll 	    ((hdrp->flags & BTH5_FLAGS_CRC_PRESENT) ? sizeof(crc) : 0);
    830  1.4.2.2  skrll 	if (pldlen > 0xfff) {
    831  1.4.2.2  skrll 		discard = 1;
    832  1.4.2.2  skrll 		errstr = "Payload Length";
    833  1.4.2.2  skrll 		goto discarded;
    834  1.4.2.2  skrll 	}
    835  1.4.2.2  skrll 	if (hdrp->csum != BTH5_GET_CSUM(hdrp)) {
    836  1.4.2.2  skrll 		discard = 1;
    837  1.4.2.2  skrll 		errstr = "Checksum";
    838  1.4.2.2  skrll 		goto discarded;
    839  1.4.2.2  skrll 	}
    840  1.4.2.2  skrll 	if (BTH5_GET_PLEN(hdrp) != pldlen) {
    841  1.4.2.2  skrll 		discard = 1;
    842  1.4.2.2  skrll 		errstr = "Payload Length";
    843  1.4.2.2  skrll 		goto discarded;
    844  1.4.2.2  skrll 	}
    845  1.4.2.2  skrll 	if (hdrp->flags & BTH5_FLAGS_CRC_PRESENT) {
    846  1.4.2.2  skrll 		struct mbuf *_m;
    847  1.4.2.2  skrll 		int i, n;
    848  1.4.2.2  skrll 		uint16_t crc0;
    849  1.4.2.2  skrll 		uint8_t *buf;
    850  1.4.2.2  skrll 
    851  1.4.2.2  skrll 		i = 0;
    852  1.4.2.2  skrll 		n = 0;
    853  1.4.2.2  skrll 		for (_m = m; _m != NULL; _m = _m->m_next) {
    854  1.4.2.2  skrll 			buf = mtod(m, uint8_t *);
    855  1.4.2.2  skrll 			for (n = 0;
    856  1.4.2.2  skrll 			    n < _m->m_len && i < sizeof(bth5_hdr_t) + pldlen;
    857  1.4.2.2  skrll 			    n++, i++)
    858  1.4.2.2  skrll 				bth5_crc_update(&crc, *(buf + n));
    859  1.4.2.2  skrll 		}
    860  1.4.2.2  skrll 
    861  1.4.2.2  skrll 		m_copydata(_m, n, sizeof(crc0), &crc0);
    862  1.4.2.2  skrll 		if (be16toh(crc0) != bth5_crc_reverse(crc)) {
    863  1.4.2.2  skrll 			discard = 1;
    864  1.4.2.2  skrll 			errstr = "CRC";
    865  1.4.2.2  skrll 		} else
    866  1.4.2.2  skrll 			/* Shaves CRC */
    867  1.4.2.2  skrll 			m_adj(m, (int)(0 - sizeof(crc)));
    868  1.4.2.2  skrll 	}
    869  1.4.2.2  skrll 
    870  1.4.2.2  skrll 	if (discard) {
    871  1.4.2.2  skrll discarded:
    872  1.4.2.2  skrll #ifdef BTH5_DEBUG
    873  1.4.2.2  skrll 		DPRINTFN(3, ("%s: receives unexpected packet: %s\n",
    874  1.4.2.2  skrll 		    device_xname(sc->sc_dev), errstr));
    875  1.4.2.2  skrll #else
    876  1.4.2.2  skrll 		__USE(errstr);
    877  1.4.2.2  skrll #endif
    878  1.4.2.2  skrll 		m_freem(m);
    879  1.4.2.2  skrll 	} else
    880  1.4.2.2  skrll 		bth5_mux_receive(sc, m);
    881  1.4.2.2  skrll }
    882  1.4.2.2  skrll 
    883  1.4.2.2  skrll static const uint16_t crctbl[] = {
    884  1.4.2.2  skrll 	0x0000, 0x1081, 0x2102, 0x3183,
    885  1.4.2.2  skrll 	0x4204, 0x5285, 0x6306, 0x7387,
    886  1.4.2.2  skrll 	0x8408, 0x9489, 0xa50a, 0xb58b,
    887  1.4.2.2  skrll 	0xc60c, 0xd68d, 0xe70e, 0xf78f,
    888  1.4.2.2  skrll };
    889  1.4.2.2  skrll 
    890  1.4.2.2  skrll static void
    891  1.4.2.2  skrll bth5_crc_update(uint16_t *crc, uint8_t d)
    892  1.4.2.2  skrll {
    893  1.4.2.2  skrll 	uint16_t reg = *crc;
    894  1.4.2.2  skrll 
    895  1.4.2.2  skrll 	reg = (reg >> 4) ^ crctbl[(reg ^ d) & 0x000f];
    896  1.4.2.2  skrll 	reg = (reg >> 4) ^ crctbl[(reg ^ (d >> 4)) & 0x000f];
    897  1.4.2.2  skrll 
    898  1.4.2.2  skrll 	*crc = reg;
    899  1.4.2.2  skrll }
    900  1.4.2.2  skrll 
    901  1.4.2.2  skrll static uint16_t
    902  1.4.2.2  skrll bth5_crc_reverse(uint16_t crc)
    903  1.4.2.2  skrll {
    904  1.4.2.2  skrll 	uint16_t b, rev;
    905  1.4.2.2  skrll 
    906  1.4.2.2  skrll 	for (b = 0, rev = 0; b < 16; b++) {
    907  1.4.2.2  skrll 		rev = rev << 1;
    908  1.4.2.2  skrll 		rev |= (crc & 1);
    909  1.4.2.2  skrll 		crc = crc >> 1;
    910  1.4.2.2  skrll 	}
    911  1.4.2.2  skrll 
    912  1.4.2.2  skrll 	return rev;
    913  1.4.2.2  skrll }
    914  1.4.2.2  skrll 
    915  1.4.2.2  skrll 
    916  1.4.2.2  skrll /*
    917  1.4.2.2  skrll  * BTH5 MUX Layer functions
    918  1.4.2.2  skrll  */
    919  1.4.2.2  skrll static void
    920  1.4.2.2  skrll bth5_mux_transmit(struct bth5_softc *sc)
    921  1.4.2.2  skrll {
    922  1.4.2.2  skrll 	struct mbuf *m;
    923  1.4.2.2  skrll 	bth5_hdr_t *hdrp;
    924  1.4.2.2  skrll 
    925  1.4.2.2  skrll 	DPRINTFN(2, ("%s: mux transmit: sc_flags=0x%x, choke=%d",
    926  1.4.2.2  skrll 	    device_xname(sc->sc_dev), sc->sc_flags, sc->sc_mux_choke));
    927  1.4.2.2  skrll 
    928  1.4.2.2  skrll 	if (sc->sc_mux_choke) {
    929  1.4.2.2  skrll 		struct mbuf *_m = NULL;
    930  1.4.2.2  skrll 
    931  1.4.2.2  skrll 		/* In this case, send only Link Establishment packet */
    932  1.4.2.2  skrll 		for (m = MBUFQ_FIRST(&sc->sc_dgq); m != NULL;
    933  1.4.2.2  skrll 		    _m = m, m = MBUFQ_NEXT(m)) {
    934  1.4.2.2  skrll 			hdrp = mtod(m, bth5_hdr_t *);
    935  1.4.2.2  skrll 			if (hdrp->ident == BTH5_CHANNEL_LE) {
    936  1.4.2.2  skrll 				if (m == MBUFQ_FIRST(&sc->sc_dgq))
    937  1.4.2.2  skrll 					MBUFQ_DEQUEUE(&sc->sc_dgq, m);
    938  1.4.2.2  skrll 				else {
    939  1.4.2.2  skrll 					if (m->m_nextpkt == NULL)
    940  1.4.2.2  skrll 						sc->sc_dgq.mq_last =
    941  1.4.2.2  skrll 						    &_m->m_nextpkt;
    942  1.4.2.2  skrll 					_m->m_nextpkt = m->m_nextpkt;
    943  1.4.2.2  skrll 					m->m_nextpkt = NULL;
    944  1.4.2.2  skrll 				}
    945  1.4.2.2  skrll 				goto transmit;
    946  1.4.2.2  skrll 			}
    947  1.4.2.2  skrll 		}
    948  1.4.2.2  skrll 		DPRINTFN(2, ("\n"));
    949  1.4.2.2  skrll 		return;
    950  1.4.2.2  skrll 	}
    951  1.4.2.2  skrll 
    952  1.4.2.2  skrll 	/*
    953  1.4.2.2  skrll 	 * The MUX Layer always gives priority to packets from the Datagram
    954  1.4.2.2  skrll 	 * Queue Layer over the Sequencing Layer.
    955  1.4.2.2  skrll 	 */
    956  1.4.2.2  skrll 	if (MBUFQ_FIRST(&sc->sc_dgq)) {
    957  1.4.2.2  skrll 		MBUFQ_DEQUEUE(&sc->sc_dgq, m);
    958  1.4.2.2  skrll 		goto transmit;
    959  1.4.2.2  skrll 	}
    960  1.4.2.2  skrll 	if (MBUFQ_FIRST(&sc->sc_seqq)) {
    961  1.4.2.2  skrll 		MBUFQ_DEQUEUE(&sc->sc_seqq, m);
    962  1.4.2.2  skrll 		hdrp = mtod(m, bth5_hdr_t *);
    963  1.4.2.2  skrll 		hdrp->flags |= BTH5_FLAGS_PROTOCOL_REL;		/* Reliable */
    964  1.4.2.2  skrll 		goto transmit;
    965  1.4.2.2  skrll 	}
    966  1.4.2.2  skrll 	sc->sc_flags &= ~BTH5_XMIT;
    967  1.4.2.2  skrll 	bth5_start(sc);
    968  1.4.2.2  skrll 	if (sc->sc_mux_send_ack == true) {
    969  1.4.2.2  skrll 		m = bth5_create_ackpkt();
    970  1.4.2.2  skrll 		if (m != NULL)
    971  1.4.2.2  skrll 			goto transmit;
    972  1.4.2.2  skrll 		aprint_error_dev(sc->sc_dev, "out of memory\n");
    973  1.4.2.2  skrll 		sc->sc_stats.err_tx++;
    974  1.4.2.2  skrll 	}
    975  1.4.2.2  skrll 
    976  1.4.2.2  skrll 	/* Nothing to send */
    977  1.4.2.2  skrll 	DPRINTFN(2, ("\n"));
    978  1.4.2.2  skrll 	return;
    979  1.4.2.2  skrll 
    980  1.4.2.2  skrll transmit:
    981  1.4.2.2  skrll 	DPRINTFN(2, (", txack=%d, send_ack=%d\n",
    982  1.4.2.2  skrll 	    bth5_get_txack(sc), sc->sc_mux_send_ack));
    983  1.4.2.2  skrll 
    984  1.4.2.2  skrll 	hdrp = mtod(m, bth5_hdr_t *);
    985  1.4.2.2  skrll 	hdrp->flags |=
    986  1.4.2.2  skrll 	    (bth5_get_txack(sc) << BTH5_FLAGS_ACK_SHIFT) & BTH5_FLAGS_ACK_MASK;
    987  1.4.2.2  skrll 	if (sc->sc_mux_send_ack == true)
    988  1.4.2.2  skrll 		sc->sc_mux_send_ack = false;
    989  1.4.2.2  skrll 
    990  1.4.2.2  skrll #ifdef BTH5_DEBUG
    991  1.4.2.2  skrll 	if (bth5_debug == 3)
    992  1.4.2.2  skrll 		bth5_packet_print(m);
    993  1.4.2.2  skrll #endif
    994  1.4.2.2  skrll 
    995  1.4.2.2  skrll 	sc->sc_txp = m;
    996  1.4.2.2  skrll 	bth5_pktintegrity_transmit(sc);
    997  1.4.2.2  skrll }
    998  1.4.2.2  skrll 
    999  1.4.2.2  skrll static void
   1000  1.4.2.2  skrll bth5_mux_receive(struct bth5_softc *sc, struct mbuf *m)
   1001  1.4.2.2  skrll {
   1002  1.4.2.2  skrll 	bth5_hdr_t *hdrp = mtod(m, bth5_hdr_t *);
   1003  1.4.2.2  skrll 	const u_int rxack = BTH5_FLAGS_ACK(hdrp->flags);
   1004  1.4.2.2  skrll 
   1005  1.4.2.2  skrll 	DPRINTFN(2, ("%s: mux receive: flags=0x%x, ident=%d, rxack=%d\n",
   1006  1.4.2.2  skrll 	    device_xname(sc->sc_dev), hdrp->flags, hdrp->ident, rxack));
   1007  1.4.2.2  skrll #ifdef BTH5_DEBUG
   1008  1.4.2.2  skrll 	if (bth5_debug == 3)
   1009  1.4.2.2  skrll 		bth5_packet_print(m);
   1010  1.4.2.2  skrll #endif
   1011  1.4.2.2  skrll 
   1012  1.4.2.2  skrll 	bth5_signal_rxack(sc, rxack);
   1013  1.4.2.2  skrll 
   1014  1.4.2.2  skrll 	microtime(&sc->sc_mux_lastrx);
   1015  1.4.2.2  skrll 
   1016  1.4.2.2  skrll 	/* if the Ack Packet received then discard */
   1017  1.4.2.2  skrll 	if (BTH5_FLAGS_SEQ(hdrp->flags) == 0 &&
   1018  1.4.2.2  skrll 	    hdrp->ident == BTH5_IDENT_ACKPKT &&
   1019  1.4.2.2  skrll 	    BTH5_GET_PLEN(hdrp) == 0) {
   1020  1.4.2.2  skrll 		m_freem(m);
   1021  1.4.2.2  skrll 		return;
   1022  1.4.2.2  skrll 	}
   1023  1.4.2.2  skrll 
   1024  1.4.2.2  skrll 	if (hdrp->flags & BTH5_FLAGS_PROTOCOL_REL)
   1025  1.4.2.2  skrll 		bth5_sequencing_receive(sc, m);
   1026  1.4.2.2  skrll 	else
   1027  1.4.2.2  skrll 		bth5_datagramq_receive(sc, m);
   1028  1.4.2.2  skrll }
   1029  1.4.2.2  skrll 
   1030  1.4.2.2  skrll static __inline void
   1031  1.4.2.2  skrll bth5_send_ack_command(struct bth5_softc *sc)
   1032  1.4.2.2  skrll {
   1033  1.4.2.2  skrll 
   1034  1.4.2.2  skrll 	DPRINTFN(2, ("%s: mux send_ack_command\n", device_xname(sc->sc_dev)));
   1035  1.4.2.2  skrll 
   1036  1.4.2.2  skrll 	sc->sc_mux_send_ack = true;
   1037  1.4.2.2  skrll }
   1038  1.4.2.2  skrll 
   1039  1.4.2.2  skrll static __inline struct mbuf *
   1040  1.4.2.2  skrll bth5_create_ackpkt(void)
   1041  1.4.2.2  skrll {
   1042  1.4.2.2  skrll 	struct mbuf *m;
   1043  1.4.2.2  skrll 	bth5_hdr_t *hdrp;
   1044  1.4.2.2  skrll 
   1045  1.4.2.2  skrll 	MGETHDR(m, M_DONTWAIT, MT_DATA);
   1046  1.4.2.2  skrll 	if (m != NULL) {
   1047  1.4.2.2  skrll 		m->m_pkthdr.len = m->m_len = sizeof(bth5_hdr_t);
   1048  1.4.2.2  skrll 		hdrp = mtod(m, bth5_hdr_t *);
   1049  1.4.2.2  skrll 		/*
   1050  1.4.2.2  skrll 		 * An Ack Packet has the following fields:
   1051  1.4.2.2  skrll 		 *	Ack Field:			txack (not set yet)
   1052  1.4.2.2  skrll 		 *	Seq Field:			0
   1053  1.4.2.2  skrll 		 *	Protocol Identifier Field:	0
   1054  1.4.2.2  skrll 		 *	Protocol Type Field:		Any value
   1055  1.4.2.2  skrll 		 *	Payload Length Field:		0
   1056  1.4.2.2  skrll 		 */
   1057  1.4.2.2  skrll 		memset(hdrp, 0, sizeof(bth5_hdr_t));
   1058  1.4.2.2  skrll 	}
   1059  1.4.2.2  skrll 	return m;
   1060  1.4.2.2  skrll }
   1061  1.4.2.2  skrll 
   1062  1.4.2.2  skrll static __inline void
   1063  1.4.2.2  skrll bth5_set_choke(struct bth5_softc *sc, bool choke)
   1064  1.4.2.2  skrll {
   1065  1.4.2.2  skrll 
   1066  1.4.2.2  skrll 	DPRINTFN(2, ("%s: mux set choke=%d\n", device_xname(sc->sc_dev), choke));
   1067  1.4.2.2  skrll 
   1068  1.4.2.2  skrll 	sc->sc_mux_choke = choke;
   1069  1.4.2.2  skrll }
   1070  1.4.2.2  skrll 
   1071  1.4.2.2  skrll 
   1072  1.4.2.2  skrll /*
   1073  1.4.2.2  skrll  * BTH5 Sequencing Layer functions
   1074  1.4.2.2  skrll  */
   1075  1.4.2.2  skrll static void
   1076  1.4.2.2  skrll bth5_sequencing_receive(struct bth5_softc *sc, struct mbuf *m)
   1077  1.4.2.2  skrll {
   1078  1.4.2.2  skrll 	bth5_hdr_t hdr;
   1079  1.4.2.2  skrll 	uint32_t exp_rxseq, rxseq;
   1080  1.4.2.2  skrll 
   1081  1.4.2.2  skrll 	exp_rxseq = sc->sc_seq_expected_rxseq & BTH5_FLAGS_SEQ_MASK;
   1082  1.4.2.2  skrll 	m_copydata(m, 0, sizeof(bth5_hdr_t), &hdr);
   1083  1.4.2.2  skrll 	rxseq = BTH5_FLAGS_SEQ(hdr.flags);
   1084  1.4.2.2  skrll 
   1085  1.4.2.2  skrll 	DPRINTFN(1, ("%s: seq receive: rxseq=%d, expected %d\n",
   1086  1.4.2.2  skrll 	    device_xname(sc->sc_dev), rxseq, exp_rxseq));
   1087  1.4.2.2  skrll #ifdef BTH5_DEBUG
   1088  1.4.2.2  skrll 	if (bth5_debug == 2)
   1089  1.4.2.2  skrll 		bth5_packet_print(m);
   1090  1.4.2.2  skrll #endif
   1091  1.4.2.2  skrll 
   1092  1.4.2.2  skrll 	/*
   1093  1.4.2.2  skrll 	 * We remove the header of BTH5 and add the 'uint8_t type' of
   1094  1.4.2.2  skrll 	 * hci_*_hdr_t to the head.
   1095  1.4.2.2  skrll 	 */
   1096  1.4.2.2  skrll 	m_adj(m, sizeof(bth5_hdr_t) - sizeof(uint8_t));
   1097  1.4.2.2  skrll 
   1098  1.4.2.2  skrll 	if (rxseq != exp_rxseq) {
   1099  1.4.2.2  skrll 		m_freem(m);
   1100  1.4.2.2  skrll 
   1101  1.4.2.2  skrll 		bth5_send_ack_command(sc);
   1102  1.4.2.2  skrll 		/* send ack packet, if needly */
   1103  1.4.2.2  skrll 		bth5_mux_transmit(sc);
   1104  1.4.2.2  skrll 
   1105  1.4.2.2  skrll 		return;
   1106  1.4.2.2  skrll 	}
   1107  1.4.2.2  skrll 
   1108  1.4.2.2  skrll 	switch (hdr.ident) {
   1109  1.4.2.2  skrll 	case BTH5_CHANNEL_HCI_CMD:
   1110  1.4.2.2  skrll 		*(mtod(m, uint8_t *)) = HCI_CMD_PKT;
   1111  1.4.2.2  skrll 		if (!hci_input_event(sc->sc_unit, m))
   1112  1.4.2.2  skrll 			sc->sc_stats.err_rx++;
   1113  1.4.2.2  skrll 
   1114  1.4.2.2  skrll 		sc->sc_stats.evt_rx++;
   1115  1.4.2.2  skrll 		break;
   1116  1.4.2.2  skrll 
   1117  1.4.2.2  skrll 	case BTH5_CHANNEL_HCI_EVT:
   1118  1.4.2.2  skrll 		*(mtod(m, uint8_t *)) = HCI_EVENT_PKT;
   1119  1.4.2.2  skrll 		if (!hci_input_event(sc->sc_unit, m))
   1120  1.4.2.2  skrll 			sc->sc_stats.err_rx++;
   1121  1.4.2.2  skrll 
   1122  1.4.2.2  skrll 		sc->sc_stats.evt_rx++;
   1123  1.4.2.2  skrll 		break;
   1124  1.4.2.2  skrll 
   1125  1.4.2.2  skrll 	case BTH5_CHANNEL_HCI_ACL:
   1126  1.4.2.2  skrll 		*(mtod(m, uint8_t *)) = HCI_ACL_DATA_PKT;
   1127  1.4.2.2  skrll 		if (!hci_input_acl(sc->sc_unit, m))
   1128  1.4.2.2  skrll 			sc->sc_stats.err_rx++;
   1129  1.4.2.2  skrll 
   1130  1.4.2.2  skrll 		sc->sc_stats.acl_rx++;
   1131  1.4.2.2  skrll 		break;
   1132  1.4.2.2  skrll 
   1133  1.4.2.2  skrll 	case BTH5_CHANNEL_HCI_SCO:
   1134  1.4.2.2  skrll 		*(mtod(m, uint8_t *)) = HCI_SCO_DATA_PKT;
   1135  1.4.2.2  skrll 		if (!hci_input_sco(sc->sc_unit, m))
   1136  1.4.2.2  skrll 			sc->sc_stats.err_rx++;
   1137  1.4.2.2  skrll 
   1138  1.4.2.2  skrll 		sc->sc_stats.sco_rx++;
   1139  1.4.2.2  skrll 		break;
   1140  1.4.2.2  skrll 
   1141  1.4.2.2  skrll 	default:
   1142  1.4.2.2  skrll 		aprint_error_dev(sc->sc_dev,
   1143  1.4.2.2  skrll 		    "received reliable packet with not support channel %d\n",
   1144  1.4.2.2  skrll 		    hdr.ident);
   1145  1.4.2.2  skrll 		m_freem(m);
   1146  1.4.2.2  skrll 		break;
   1147  1.4.2.2  skrll 	}
   1148  1.4.2.2  skrll 
   1149  1.4.2.2  skrll 	if (sc->sc_seq_expected_rxseq / sc->sc_seq_winsize  ==
   1150  1.4.2.2  skrll 					 sc->sc_seq_winsize) {
   1151  1.4.2.2  skrll 		bth5_send_ack_command(sc);
   1152  1.4.2.2  skrll 		sc->sc_seq_txack = sc->sc_seq_expected_rxseq & BTH5_FLAGS_SEQ_MASK;
   1153  1.4.2.2  skrll 	} else
   1154  1.4.2.2  skrll 		sc->sc_seq_txack = rxseq;
   1155  1.4.2.2  skrll 
   1156  1.4.2.2  skrll 	sc->sc_seq_expected_rxseq =
   1157  1.4.2.2  skrll 	    (sc->sc_seq_expected_rxseq + 1);
   1158  1.4.2.2  skrll }
   1159  1.4.2.2  skrll 
   1160  1.4.2.2  skrll static bool
   1161  1.4.2.2  skrll bth5_tx_reliable_pkt(struct bth5_softc *sc, struct mbuf *m, u_int protocol_id)
   1162  1.4.2.2  skrll {
   1163  1.4.2.2  skrll 	bth5_hdr_t *hdrp;
   1164  1.4.2.2  skrll 	struct mbuf *_m;
   1165  1.4.2.2  skrll 	struct mbuf *_retrans;
   1166  1.4.2.2  skrll 	u_int pldlen;
   1167  1.4.2.2  skrll 	int s;
   1168  1.4.2.2  skrll 
   1169  1.4.2.2  skrll 	DPRINTFN(1, ("%s: seq transmit:"
   1170  1.4.2.2  skrll 	    "protocol_id=%d, winspace=%d, txseq=%d\n", device_xname(sc->sc_dev),
   1171  1.4.2.2  skrll 	    protocol_id, sc->sc_seq_winspace, sc->sc_seq_txseq));
   1172  1.4.2.2  skrll 
   1173  1.4.2.2  skrll 	for (pldlen = 0, _m = m; _m != NULL; _m = _m->m_next) {
   1174  1.4.2.2  skrll 		if (_m->m_len < 0)
   1175  1.4.2.2  skrll 			goto out;
   1176  1.4.2.2  skrll 		pldlen += _m->m_len;
   1177  1.4.2.2  skrll 	}
   1178  1.4.2.2  skrll 	if (pldlen > 0xfff)
   1179  1.4.2.2  skrll 		goto out;
   1180  1.4.2.2  skrll 	if (protocol_id == BTH5_IDENT_ACKPKT || protocol_id > 15)
   1181  1.4.2.2  skrll 		goto out;
   1182  1.4.2.2  skrll 
   1183  1.4.2.2  skrll 	if (sc->sc_seq_winspace == 0)
   1184  1.4.2.2  skrll 		goto out;
   1185  1.4.2.2  skrll 
   1186  1.4.2.2  skrll 	M_PREPEND(m, sizeof(bth5_hdr_t), M_DONTWAIT);
   1187  1.4.2.2  skrll 	if (m == NULL) {
   1188  1.4.2.2  skrll 		aprint_error_dev(sc->sc_dev, "out of memory\n");
   1189  1.4.2.2  skrll 		return false;
   1190  1.4.2.2  skrll 	}
   1191  1.4.2.2  skrll 	KASSERT(m->m_len >= sizeof(bth5_hdr_t));
   1192  1.4.2.2  skrll 
   1193  1.4.2.2  skrll 	hdrp = mtod(m, bth5_hdr_t *);
   1194  1.4.2.2  skrll 	memset(hdrp, 0, sizeof(bth5_hdr_t));
   1195  1.4.2.2  skrll 	hdrp->flags |= sc->sc_seq_txseq;
   1196  1.4.2.2  skrll 	hdrp->ident = protocol_id;
   1197  1.4.2.2  skrll 
   1198  1.4.2.2  skrll 	callout_schedule(&sc->sc_seq_timer, sc->sc_seq_timeout);
   1199  1.4.2.2  skrll 
   1200  1.4.2.2  skrll 	s = splserial();
   1201  1.4.2.2  skrll 	MBUFQ_ENQUEUE(&sc->sc_seqq, m);
   1202  1.4.2.2  skrll 	splx(s);
   1203  1.4.2.2  skrll 	sc->sc_transmit_callback = bth5_reliabletx_callback;
   1204  1.4.2.2  skrll 
   1205  1.4.2.2  skrll #ifdef BTH5_DEBUG
   1206  1.4.2.2  skrll 	if (bth5_debug == 2)
   1207  1.4.2.2  skrll 		bth5_packet_print(m);
   1208  1.4.2.2  skrll #endif
   1209  1.4.2.2  skrll 
   1210  1.4.2.2  skrll 	sc->sc_seq_txseq = (sc->sc_seq_txseq + 1) & BTH5_FLAGS_SEQ_MASK;
   1211  1.4.2.2  skrll 	sc->sc_seq_winspace--;
   1212  1.4.2.2  skrll 	_retrans = m_copym(m, 0, M_COPYALL, M_WAIT);
   1213  1.4.2.2  skrll 	if (_retrans == NULL) {
   1214  1.4.2.2  skrll 		aprint_error_dev(sc->sc_dev, "out of memory\n");
   1215  1.4.2.2  skrll 		goto out;
   1216  1.4.2.2  skrll 	}
   1217  1.4.2.2  skrll 	MBUFQ_ENQUEUE(&sc->sc_seq_retryq, _retrans);
   1218  1.4.2.2  skrll 	bth5_mux_transmit(sc);
   1219  1.4.2.2  skrll 
   1220  1.4.2.2  skrll 	return true;
   1221  1.4.2.2  skrll out:
   1222  1.4.2.2  skrll 	m_freem(m);
   1223  1.4.2.2  skrll 	return false;
   1224  1.4.2.2  skrll }
   1225  1.4.2.2  skrll 
   1226  1.4.2.2  skrll static __inline u_int
   1227  1.4.2.2  skrll bth5_get_txack(struct bth5_softc *sc)
   1228  1.4.2.2  skrll {
   1229  1.4.2.2  skrll 
   1230  1.4.2.2  skrll 	return sc->sc_seq_txack;
   1231  1.4.2.2  skrll }
   1232  1.4.2.2  skrll 
   1233  1.4.2.2  skrll static void
   1234  1.4.2.2  skrll bth5_signal_rxack(struct bth5_softc *sc, uint32_t rxack)
   1235  1.4.2.2  skrll {
   1236  1.4.2.2  skrll 	bth5_hdr_t *hdrp;
   1237  1.4.2.2  skrll 	struct mbuf *m;
   1238  1.4.2.2  skrll 	uint32_t seqno = (rxack - 1) & BTH5_FLAGS_SEQ_MASK;
   1239  1.4.2.2  skrll 	int s;
   1240  1.4.2.2  skrll 
   1241  1.4.2.2  skrll 	DPRINTFN(1, ("%s: seq signal rxack: rxack=%d\n",
   1242  1.4.2.2  skrll 	    device_xname(sc->sc_dev), rxack));
   1243  1.4.2.2  skrll 
   1244  1.4.2.2  skrll 	s = splserial();
   1245  1.4.2.2  skrll 	m = MBUFQ_FIRST(&sc->sc_seq_retryq);
   1246  1.4.2.2  skrll 	while (m != NULL) {
   1247  1.4.2.2  skrll 		hdrp = mtod(m, bth5_hdr_t *);
   1248  1.4.2.2  skrll 		if (BTH5_FLAGS_SEQ(hdrp->flags) == seqno) {
   1249  1.4.2.2  skrll 			struct mbuf *m0;
   1250  1.4.2.2  skrll 
   1251  1.4.2.2  skrll 			for (m0 = MBUFQ_FIRST(&sc->sc_seq_retryq);
   1252  1.4.2.2  skrll 			    m0 != MBUFQ_NEXT(m);
   1253  1.4.2.2  skrll 			    m0 = MBUFQ_FIRST(&sc->sc_seq_retryq)) {
   1254  1.4.2.2  skrll 				MBUFQ_DEQUEUE(&sc->sc_seq_retryq, m0);
   1255  1.4.2.2  skrll 				m_freem(m0);
   1256  1.4.2.2  skrll 				sc->sc_seq_winspace++;
   1257  1.4.2.2  skrll 			}
   1258  1.4.2.2  skrll 			break;
   1259  1.4.2.2  skrll 		}
   1260  1.4.2.2  skrll 		m = MBUFQ_NEXT(m);
   1261  1.4.2.2  skrll 	}
   1262  1.4.2.2  skrll 	splx(s);
   1263  1.4.2.2  skrll 	sc->sc_seq_retries = 0;
   1264  1.4.2.2  skrll 
   1265  1.4.2.2  skrll 	if (sc->sc_seq_winspace == sc->sc_seq_winsize)
   1266  1.4.2.2  skrll 		callout_stop(&sc->sc_seq_timer);
   1267  1.4.2.2  skrll 	else
   1268  1.4.2.2  skrll 		callout_schedule(&sc->sc_seq_timer, sc->sc_seq_timeout);
   1269  1.4.2.2  skrll }
   1270  1.4.2.2  skrll 
   1271  1.4.2.2  skrll static void
   1272  1.4.2.2  skrll bth5_reliabletx_callback(struct bth5_softc *sc, struct mbuf *m)
   1273  1.4.2.2  skrll {
   1274  1.4.2.2  skrll 
   1275  1.4.2.2  skrll 	m_freem(m);
   1276  1.4.2.2  skrll }
   1277  1.4.2.2  skrll 
   1278  1.4.2.2  skrll static void
   1279  1.4.2.2  skrll bth5_timer_timeout(void *arg)
   1280  1.4.2.2  skrll {
   1281  1.4.2.2  skrll 	struct bth5_softc *sc = arg;
   1282  1.4.2.2  skrll 	struct mbuf *m, *_m;
   1283  1.4.2.2  skrll 	int s, i = 0;
   1284  1.4.2.2  skrll 
   1285  1.4.2.2  skrll 	DPRINTFN(1, ("%s: seq timeout: retries=%d\n",
   1286  1.4.2.2  skrll 	    device_xname(sc->sc_dev), sc->sc_seq_retries));
   1287  1.4.2.2  skrll 
   1288  1.4.2.2  skrll 	s = splserial();
   1289  1.4.2.2  skrll 	for (m = MBUFQ_FIRST(&sc->sc_seq_retryq); m != NULL;
   1290  1.4.2.2  skrll 	    m = MBUFQ_NEXT(m)) {
   1291  1.4.2.2  skrll 		_m = m_copym(m, 0, M_COPYALL, M_DONTWAIT);
   1292  1.4.2.2  skrll 		if (_m == NULL) {
   1293  1.4.2.2  skrll 			aprint_error_dev(sc->sc_dev, "out of memory\n");
   1294  1.4.2.2  skrll 			return;
   1295  1.4.2.2  skrll 		}
   1296  1.4.2.2  skrll 		MBUFQ_ENQUEUE(&sc->sc_seqq, _m);
   1297  1.4.2.2  skrll 		i++;
   1298  1.4.2.2  skrll 	}
   1299  1.4.2.2  skrll 	splx(s);
   1300  1.4.2.2  skrll 
   1301  1.4.2.2  skrll 	if (i != 0) {
   1302  1.4.2.2  skrll 		if (++sc->sc_seq_retries < sc->sc_seq_retry_limit)
   1303  1.4.2.2  skrll 			callout_schedule(&sc->sc_seq_timer, sc->sc_seq_timeout);
   1304  1.4.2.2  skrll 		else {
   1305  1.4.2.2  skrll 			aprint_error_dev(sc->sc_dev,
   1306  1.4.2.2  skrll 			    "reached the retry limit."
   1307  1.4.2.2  skrll 			    " restart the link-establishment\n");
   1308  1.4.2.2  skrll 			bth5_sequencing_reset(sc);
   1309  1.4.2.2  skrll 			bth5_start_le(sc);
   1310  1.4.2.2  skrll 			return;
   1311  1.4.2.2  skrll 		}
   1312  1.4.2.2  skrll 	}
   1313  1.4.2.2  skrll 	bth5_mux_transmit(sc);
   1314  1.4.2.2  skrll }
   1315  1.4.2.2  skrll 
   1316  1.4.2.2  skrll static void
   1317  1.4.2.2  skrll bth5_sequencing_reset(struct bth5_softc *sc)
   1318  1.4.2.2  skrll {
   1319  1.4.2.2  skrll 	int s;
   1320  1.4.2.2  skrll 
   1321  1.4.2.2  skrll 	s = splserial();
   1322  1.4.2.2  skrll 	MBUFQ_DRAIN(&sc->sc_seqq);
   1323  1.4.2.2  skrll 	MBUFQ_DRAIN(&sc->sc_seq_retryq);
   1324  1.4.2.2  skrll 	splx(s);
   1325  1.4.2.2  skrll 
   1326  1.4.2.2  skrll 
   1327  1.4.2.2  skrll 	sc->sc_seq_txseq = 0;
   1328  1.4.2.2  skrll 	sc->sc_seq_txack = 0;
   1329  1.4.2.2  skrll 	sc->sc_seq_winspace = sc->sc_seq_winsize;
   1330  1.4.2.2  skrll 	sc->sc_seq_retries = 0;
   1331  1.4.2.2  skrll 	callout_stop(&sc->sc_seq_timer);
   1332  1.4.2.2  skrll 
   1333  1.4.2.2  skrll 	sc->sc_mux_send_ack = false;
   1334  1.4.2.2  skrll 
   1335  1.4.2.2  skrll 	/* XXXX: expected_rxseq should be set by MUX Layer */
   1336  1.4.2.2  skrll 	sc->sc_seq_expected_rxseq = 0;
   1337  1.4.2.2  skrll }
   1338  1.4.2.2  skrll 
   1339  1.4.2.2  skrll 
   1340  1.4.2.2  skrll /*
   1341  1.4.2.2  skrll  * BTH5 Datagram Queue Layer functions
   1342  1.4.2.2  skrll  */
   1343  1.4.2.2  skrll static void
   1344  1.4.2.2  skrll bth5_datagramq_receive(struct bth5_softc *sc, struct mbuf *m)
   1345  1.4.2.2  skrll {
   1346  1.4.2.2  skrll 	bth5_hdr_t hdr;
   1347  1.4.2.2  skrll 
   1348  1.4.2.2  skrll 	DPRINTFN(1, ("%s: dgq receive\n", device_xname(sc->sc_dev)));
   1349  1.4.2.2  skrll #ifdef BTH5_DEBUG
   1350  1.4.2.2  skrll 	if (bth5_debug == 2)
   1351  1.4.2.2  skrll 		bth5_packet_print(m);
   1352  1.4.2.2  skrll #endif
   1353  1.4.2.2  skrll 
   1354  1.4.2.2  skrll 	m_copydata(m, 0, sizeof(bth5_hdr_t), &hdr);
   1355  1.4.2.2  skrll 
   1356  1.4.2.2  skrll 	switch (hdr.ident) {
   1357  1.4.2.2  skrll 	case BTH5_CHANNEL_LE:
   1358  1.4.2.2  skrll 		m_adj(m, sizeof(bth5_hdr_t));
   1359  1.4.2.2  skrll 		bth5_input_le(sc, m);
   1360  1.4.2.2  skrll 		break;
   1361  1.4.2.2  skrll 
   1362  1.4.2.2  skrll 	case BTH5_CHANNEL_HCI_SCO:
   1363  1.4.2.2  skrll 		/*
   1364  1.4.2.2  skrll 		 * We remove the header of BTH5 and add the 'uint8_t type' of
   1365  1.4.2.2  skrll 		 * hci_scodata_hdr_t to the head.
   1366  1.4.2.2  skrll 		 */
   1367  1.4.2.2  skrll 		m_adj(m, sizeof(bth5_hdr_t) - sizeof(uint8_t));
   1368  1.4.2.2  skrll 		*(mtod(m, uint8_t *)) = HCI_SCO_DATA_PKT;
   1369  1.4.2.2  skrll 		if (!hci_input_sco(sc->sc_unit, m))
   1370  1.4.2.2  skrll 			sc->sc_stats.err_rx++;
   1371  1.4.2.2  skrll 
   1372  1.4.2.2  skrll 		sc->sc_stats.sco_rx++;
   1373  1.4.2.2  skrll 		break;
   1374  1.4.2.2  skrll 
   1375  1.4.2.2  skrll 	default:
   1376  1.4.2.2  skrll 		aprint_error_dev(sc->sc_dev,
   1377  1.4.2.2  skrll 		    "received unreliable packet with not support channel %d\n",
   1378  1.4.2.2  skrll 		    hdr.ident);
   1379  1.4.2.2  skrll 		m_freem(m);
   1380  1.4.2.2  skrll 		break;
   1381  1.4.2.2  skrll 	}
   1382  1.4.2.2  skrll }
   1383  1.4.2.2  skrll 
   1384  1.4.2.2  skrll static bool
   1385  1.4.2.2  skrll bth5_tx_unreliable_pkt(struct bth5_softc *sc, struct mbuf *m, u_int protocol_id)
   1386  1.4.2.2  skrll {
   1387  1.4.2.2  skrll 	bth5_hdr_t *hdrp;
   1388  1.4.2.2  skrll 	struct mbuf *_m;
   1389  1.4.2.2  skrll 	u_int pldlen;
   1390  1.4.2.2  skrll 	int s;
   1391  1.4.2.2  skrll 
   1392  1.4.2.2  skrll 	DPRINTFN(1, ("%s: dgq transmit: protocol_id=%d,",
   1393  1.4.2.2  skrll 	    device_xname(sc->sc_dev), protocol_id));
   1394  1.4.2.2  skrll 
   1395  1.4.2.2  skrll 	for (pldlen = 0, _m = m; _m != NULL; _m = m->m_next) {
   1396  1.4.2.2  skrll 		if (_m->m_len < 0)
   1397  1.4.2.2  skrll 			goto out;
   1398  1.4.2.2  skrll 		pldlen += _m->m_len;
   1399  1.4.2.2  skrll 	}
   1400  1.4.2.2  skrll 	DPRINTFN(1, (" pldlen=%d\n", pldlen));
   1401  1.4.2.2  skrll 	if (pldlen > 0xfff)
   1402  1.4.2.2  skrll 		goto out;
   1403  1.4.2.2  skrll 	if (protocol_id == BTH5_IDENT_ACKPKT || protocol_id > 15)
   1404  1.4.2.2  skrll 		goto out;
   1405  1.4.2.2  skrll 
   1406  1.4.2.2  skrll 	M_PREPEND(m, sizeof(bth5_hdr_t), M_DONTWAIT);
   1407  1.4.2.2  skrll 	if (m == NULL) {
   1408  1.4.2.2  skrll 		aprint_error_dev(sc->sc_dev, "out of memory\n");
   1409  1.4.2.2  skrll 		return false;
   1410  1.4.2.2  skrll 	}
   1411  1.4.2.2  skrll 	KASSERT(m->m_len >= sizeof(bth5_hdr_t));
   1412  1.4.2.2  skrll 
   1413  1.4.2.2  skrll 	hdrp = mtod(m, bth5_hdr_t *);
   1414  1.4.2.2  skrll 	memset(hdrp, 0, sizeof(bth5_hdr_t));
   1415  1.4.2.2  skrll 	hdrp->ident = protocol_id;
   1416  1.4.2.2  skrll 
   1417  1.4.2.2  skrll 	s = splserial();
   1418  1.4.2.2  skrll 	MBUFQ_ENQUEUE(&sc->sc_dgq, m);
   1419  1.4.2.2  skrll 	splx(s);
   1420  1.4.2.2  skrll 	sc->sc_transmit_callback = bth5_unreliabletx_callback;
   1421  1.4.2.2  skrll 
   1422  1.4.2.2  skrll #ifdef BTH5_DEBUG
   1423  1.4.2.2  skrll 	if (bth5_debug == 2)
   1424  1.4.2.2  skrll 		bth5_packet_print(m);
   1425  1.4.2.2  skrll #endif
   1426  1.4.2.2  skrll 
   1427  1.4.2.2  skrll 	bth5_mux_transmit(sc);
   1428  1.4.2.2  skrll 
   1429  1.4.2.2  skrll 	return true;
   1430  1.4.2.2  skrll out:
   1431  1.4.2.2  skrll 	m_freem(m);
   1432  1.4.2.2  skrll 	return false;
   1433  1.4.2.2  skrll }
   1434  1.4.2.2  skrll 
   1435  1.4.2.2  skrll static void
   1436  1.4.2.2  skrll bth5_unreliabletx_callback(struct bth5_softc *sc, struct mbuf *m)
   1437  1.4.2.2  skrll {
   1438  1.4.2.2  skrll 
   1439  1.4.2.2  skrll 	if (M_GETCTX(m, void *) == NULL)
   1440  1.4.2.2  skrll 		m_freem(m);
   1441  1.4.2.2  skrll 	else if (!hci_complete_sco(sc->sc_unit, m))
   1442  1.4.2.2  skrll 		sc->sc_stats.err_tx++;
   1443  1.4.2.2  skrll }
   1444  1.4.2.2  skrll 
   1445  1.4.2.2  skrll 
   1446  1.4.2.2  skrll /*
   1447  1.4.2.2  skrll  * BTUART H5 Link Establishment Protocol functions
   1448  1.4.2.2  skrll  */
   1449  1.4.2.2  skrll static const uint8_t sync[] = BTH5_LE_SYNC;
   1450  1.4.2.2  skrll static const uint8_t syncresp[] = BTH5_LE_SYNCRESP;
   1451  1.4.2.2  skrll static const uint8_t conf[] = BTH5_LE_CONF;
   1452  1.4.2.2  skrll static const uint8_t confresp[] = BTH5_LE_CONFRESP;
   1453  1.4.2.2  skrll 
   1454  1.4.2.2  skrll static int
   1455  1.4.2.2  skrll bth5_start_le(struct bth5_softc *sc)
   1456  1.4.2.2  skrll {
   1457  1.4.2.2  skrll 
   1458  1.4.2.2  skrll 	DPRINTF(("%s: start link-establish\n", device_xname(sc->sc_dev)));
   1459  1.4.2.2  skrll 
   1460  1.4.2.2  skrll 	bth5_set_choke(sc, true);
   1461  1.4.2.2  skrll 
   1462  1.4.2.2  skrll 	if (!sc->sc_le_muzzled) {
   1463  1.4.2.2  skrll 		struct mbuf *m;
   1464  1.4.2.2  skrll 
   1465  1.4.2.2  skrll 		m = m_gethdr(M_WAIT, MT_DATA);
   1466  1.4.2.2  skrll 		m->m_pkthdr.len = m->m_len = 0;
   1467  1.4.2.2  skrll 		m_copyback(m, 0, sizeof(sync), sync);
   1468  1.4.2.2  skrll 		if (!bth5_tx_unreliable_pkt(sc, m, BTH5_CHANNEL_LE)) {
   1469  1.4.2.2  skrll 			aprint_error_dev(sc->sc_dev,
   1470  1.4.2.2  skrll 			    "le-packet transmit failed\n");
   1471  1.4.2.2  skrll 			return EINVAL;
   1472  1.4.2.2  skrll 		}
   1473  1.4.2.2  skrll 	}
   1474  1.4.2.2  skrll 	callout_schedule(&sc->sc_le_timer, BTH5_LE_TSHY_TIMEOUT);
   1475  1.4.2.2  skrll 
   1476  1.4.2.2  skrll 	sc->sc_le_state = le_state_shy;
   1477  1.4.2.2  skrll 	return 0;
   1478  1.4.2.2  skrll }
   1479  1.4.2.2  skrll 
   1480  1.4.2.2  skrll static void
   1481  1.4.2.2  skrll bth5_terminate_le(struct bth5_softc *sc)
   1482  1.4.2.2  skrll {
   1483  1.4.2.2  skrll 	struct mbuf *m;
   1484  1.4.2.2  skrll 
   1485  1.4.2.2  skrll 	/* terminate link-establishment */
   1486  1.4.2.2  skrll 	callout_stop(&sc->sc_le_timer);
   1487  1.4.2.2  skrll 	bth5_set_choke(sc, true);
   1488  1.4.2.2  skrll 	MGETHDR(m, M_DONTWAIT, MT_DATA);
   1489  1.4.2.2  skrll 	if (m == NULL)
   1490  1.4.2.2  skrll 		aprint_error_dev(sc->sc_dev, "out of memory\n");
   1491  1.4.2.2  skrll 	else {
   1492  1.4.2.2  skrll 		/* length of le packets is 4 */
   1493  1.4.2.2  skrll 		m->m_pkthdr.len = m->m_len = 0;
   1494  1.4.2.2  skrll 		m_copyback(m, 0, sizeof(sync), sync);
   1495  1.4.2.2  skrll 		if (!bth5_tx_unreliable_pkt(sc, m, BTH5_CHANNEL_LE))
   1496  1.4.2.2  skrll 			aprint_error_dev(sc->sc_dev,
   1497  1.4.2.2  skrll 			    "link-establishment terminations failed\n");
   1498  1.4.2.2  skrll 	}
   1499  1.4.2.2  skrll }
   1500  1.4.2.2  skrll 
   1501  1.4.2.2  skrll static void
   1502  1.4.2.2  skrll bth5_input_le(struct bth5_softc *sc, struct mbuf *m)
   1503  1.4.2.2  skrll {
   1504  1.4.2.2  skrll 	uint16_t *rcvpkt;
   1505  1.4.2.2  skrll 	int i;
   1506  1.4.2.2  skrll 	const uint8_t *rplypkt;
   1507  1.4.2.2  skrll 	static struct {
   1508  1.4.2.2  skrll 		const char *type;
   1509  1.4.2.2  skrll 		const uint8_t *datap;
   1510  1.4.2.2  skrll 	} pkt[] = {
   1511  1.4.2.2  skrll 		{ "sync",	sync },
   1512  1.4.2.2  skrll 		{ "sync-resp",	syncresp },
   1513  1.4.2.2  skrll 		{ "conf",	conf },
   1514  1.4.2.2  skrll 		{ "conf-resp",	confresp },
   1515  1.4.2.2  skrll 
   1516  1.4.2.2  skrll 		{ NULL, 0 }
   1517  1.4.2.2  skrll 	};
   1518  1.4.2.2  skrll 
   1519  1.4.2.2  skrll 	DPRINTFN(0, ("%s: le input: state %d, muzzled %d\n",
   1520  1.4.2.2  skrll 	    device_xname(sc->sc_dev), sc->sc_le_state, sc->sc_le_muzzled));
   1521  1.4.2.2  skrll #ifdef BTH5_DEBUG
   1522  1.4.2.2  skrll 	if (bth5_debug == 1)
   1523  1.4.2.2  skrll 		bth5_packet_print(m);
   1524  1.4.2.2  skrll #endif
   1525  1.4.2.2  skrll 
   1526  1.4.2.2  skrll 	rcvpkt = mtod(m, uint16_t *);
   1527  1.4.2.2  skrll 	i = 0;
   1528  1.4.2.2  skrll 
   1529  1.4.2.2  skrll 	/* length of le packets is 2 */
   1530  1.4.2.2  skrll 	if (m->m_len == sizeof(uint16_t))
   1531  1.4.2.2  skrll 		for (i = 0; pkt[i].type != NULL; i++)
   1532  1.4.2.2  skrll 			if (*(const uint16_t *)pkt[i].datap == *rcvpkt)
   1533  1.4.2.2  skrll 				break;
   1534  1.4.2.2  skrll 	if (m->m_len < sizeof(uint16_t) || pkt[i].type == NULL) {
   1535  1.4.2.2  skrll 		aprint_error_dev(sc->sc_dev, "received unknown packet\n");
   1536  1.4.2.2  skrll 		m_freem(m);
   1537  1.4.2.2  skrll 		return;
   1538  1.4.2.2  skrll 	}
   1539  1.4.2.2  skrll 
   1540  1.4.2.2  skrll 	rplypkt = NULL;
   1541  1.4.2.2  skrll 	switch (sc->sc_le_state) {
   1542  1.4.2.2  skrll 	case le_state_shy:
   1543  1.4.2.2  skrll 		if (*rcvpkt == *(const uint16_t *)sync) {
   1544  1.4.2.2  skrll 			sc->sc_le_muzzled = false;
   1545  1.4.2.2  skrll 			rplypkt = syncresp;
   1546  1.4.2.2  skrll 		} else if (*rcvpkt == *(const uint16_t *)syncresp) {
   1547  1.4.2.2  skrll 			DPRINTF(("%s: state change to curious\n",
   1548  1.4.2.2  skrll 			    device_xname(sc->sc_dev)));
   1549  1.4.2.2  skrll 			rplypkt = conf;
   1550  1.4.2.2  skrll 			callout_schedule(&sc->sc_le_timer,
   1551  1.4.2.2  skrll 			    BTH5_LE_TCONF_TIMEOUT);
   1552  1.4.2.2  skrll 			sc->sc_le_state = le_state_curious;
   1553  1.4.2.2  skrll 		} else
   1554  1.4.2.2  skrll 			aprint_error_dev(sc->sc_dev,
   1555  1.4.2.2  skrll 			    "received an unknown packet at shy\n");
   1556  1.4.2.2  skrll 		break;
   1557  1.4.2.2  skrll 
   1558  1.4.2.2  skrll 	case le_state_curious:
   1559  1.4.2.2  skrll 		if (*rcvpkt == *(const uint16_t *)sync)
   1560  1.4.2.2  skrll 			rplypkt = syncresp;
   1561  1.4.2.2  skrll 		else if (*rcvpkt == *(const uint16_t *)syncresp)
   1562  1.4.2.2  skrll 			rplypkt = conf;
   1563  1.4.2.2  skrll 		else if (*rcvpkt == *(const uint16_t *)conf)
   1564  1.4.2.2  skrll 			rplypkt = confresp;
   1565  1.4.2.2  skrll 		else if (*rcvpkt == *(const uint16_t *)confresp) {
   1566  1.4.2.2  skrll 			DPRINTF(("%s: state change to garrulous:\n",
   1567  1.4.2.2  skrll 			    device_xname(sc->sc_dev)));
   1568  1.4.2.2  skrll 
   1569  1.4.2.2  skrll 			bth5_set_choke(sc, false);
   1570  1.4.2.2  skrll 			callout_stop(&sc->sc_le_timer);
   1571  1.4.2.2  skrll 			sc->sc_le_state = le_state_garrulous;
   1572  1.4.2.2  skrll 		} else
   1573  1.4.2.2  skrll 			aprint_error_dev(sc->sc_dev,
   1574  1.4.2.2  skrll 			    "received unknown packet at curious\n");
   1575  1.4.2.2  skrll 		break;
   1576  1.4.2.2  skrll 
   1577  1.4.2.2  skrll 	case le_state_garrulous:
   1578  1.4.2.2  skrll 		if (*rcvpkt == *(const uint16_t *)conf)
   1579  1.4.2.2  skrll 			rplypkt = confresp;
   1580  1.4.2.2  skrll 		else if (*rcvpkt == *(const uint16_t *)sync) {
   1581  1.4.2.2  skrll 			/* XXXXX */
   1582  1.4.2.2  skrll 			aprint_error_dev(sc->sc_dev,
   1583  1.4.2.2  skrll 			    "received sync! peer to reset?\n");
   1584  1.4.2.2  skrll 
   1585  1.4.2.2  skrll 			bth5_sequencing_reset(sc);
   1586  1.4.2.2  skrll 			rplypkt = sync;
   1587  1.4.2.2  skrll 			sc->sc_le_state = le_state_shy;
   1588  1.4.2.2  skrll 		} else
   1589  1.4.2.2  skrll 			aprint_error_dev(sc->sc_dev,
   1590  1.4.2.2  skrll 			    "received unknown packet at garrulous\n");
   1591  1.4.2.2  skrll 		break;
   1592  1.4.2.2  skrll 	}
   1593  1.4.2.2  skrll 
   1594  1.4.2.2  skrll 	int len = m->m_len;
   1595  1.4.2.2  skrll 	m_freem(m);
   1596  1.4.2.2  skrll 
   1597  1.4.2.2  skrll 	if (rplypkt != NULL) {
   1598  1.4.2.2  skrll 		MGETHDR(m, M_DONTWAIT, MT_DATA);
   1599  1.4.2.2  skrll 		if (m == NULL)
   1600  1.4.2.2  skrll 			aprint_error_dev(sc->sc_dev, "out of memory\n");
   1601  1.4.2.2  skrll 		else {
   1602  1.4.2.2  skrll 			/* length of le packets is 2 */
   1603  1.4.2.2  skrll 			m->m_pkthdr.len = m->m_len = 0;
   1604  1.4.2.2  skrll 			if (rplypkt == confresp || rplypkt == conf)
   1605  1.4.2.2  skrll 				m_copyback(m, 0, len, rplypkt);
   1606  1.4.2.2  skrll 			else
   1607  1.4.2.2  skrll 				m_copyback(m, 0, 2, rplypkt);
   1608  1.4.2.2  skrll 			if (!bth5_tx_unreliable_pkt(sc, m, BTH5_CHANNEL_LE))
   1609  1.4.2.2  skrll 				aprint_error_dev(sc->sc_dev,
   1610  1.4.2.2  skrll 				    "le-packet transmit failed\n");
   1611  1.4.2.2  skrll 		}
   1612  1.4.2.2  skrll 	}
   1613  1.4.2.2  skrll }
   1614  1.4.2.2  skrll 
   1615  1.4.2.2  skrll static void
   1616  1.4.2.2  skrll bth5_le_timeout(void *arg)
   1617  1.4.2.2  skrll {
   1618  1.4.2.2  skrll 	struct bth5_softc *sc = arg;
   1619  1.4.2.2  skrll 	struct mbuf *m;
   1620  1.4.2.2  skrll 	int timeout;
   1621  1.4.2.2  skrll 	const uint8_t *sndpkt = NULL;
   1622  1.4.2.2  skrll 
   1623  1.4.2.2  skrll 	DPRINTFN(0, ("%s: le timeout: state %d, muzzled %d\n",
   1624  1.4.2.2  skrll 	    device_xname(sc->sc_dev), sc->sc_le_state, sc->sc_le_muzzled));
   1625  1.4.2.2  skrll 
   1626  1.4.2.2  skrll 	switch (sc->sc_le_state) {
   1627  1.4.2.2  skrll 	case le_state_shy:
   1628  1.4.2.2  skrll 		if (!sc->sc_le_muzzled)
   1629  1.4.2.2  skrll 			sndpkt = sync;
   1630  1.4.2.2  skrll 		timeout = BTH5_LE_TSHY_TIMEOUT;
   1631  1.4.2.2  skrll 		break;
   1632  1.4.2.2  skrll 
   1633  1.4.2.2  skrll 	case le_state_curious:
   1634  1.4.2.2  skrll 		sndpkt = conf;
   1635  1.4.2.2  skrll 		timeout = BTH5_LE_TCONF_TIMEOUT;
   1636  1.4.2.2  skrll 		break;
   1637  1.4.2.2  skrll 
   1638  1.4.2.2  skrll 	default:
   1639  1.4.2.2  skrll 		aprint_error_dev(sc->sc_dev,
   1640  1.4.2.2  skrll 		    "timeout happen at unknown state %d\n", sc->sc_le_state);
   1641  1.4.2.2  skrll 		return;
   1642  1.4.2.2  skrll 	}
   1643  1.4.2.2  skrll 
   1644  1.4.2.2  skrll 	if (sndpkt != NULL) {
   1645  1.4.2.2  skrll 		MGETHDR(m, M_DONTWAIT, MT_DATA);
   1646  1.4.2.2  skrll 		if (m == NULL)
   1647  1.4.2.2  skrll 			aprint_error_dev(sc->sc_dev, "out of memory\n");
   1648  1.4.2.2  skrll 		else {
   1649  1.4.2.2  skrll 			/* length of le packets is 4 */
   1650  1.4.2.2  skrll 			m->m_pkthdr.len = m->m_len = 0;
   1651  1.4.2.2  skrll 			if (sndpkt == conf || sndpkt == confresp)
   1652  1.4.2.2  skrll 				m_copyback(m, 0, 3, sndpkt);
   1653  1.4.2.2  skrll 			else
   1654  1.4.2.2  skrll 				m_copyback(m, 0, 2, sndpkt);
   1655  1.4.2.2  skrll 			if (!bth5_tx_unreliable_pkt(sc, m, BTH5_CHANNEL_LE))
   1656  1.4.2.2  skrll 				aprint_error_dev(sc->sc_dev,
   1657  1.4.2.2  skrll 				    "le-packet transmit failed\n");
   1658  1.4.2.2  skrll 		}
   1659  1.4.2.2  skrll 	}
   1660  1.4.2.2  skrll 
   1661  1.4.2.2  skrll 	callout_schedule(&sc->sc_le_timer, timeout);
   1662  1.4.2.2  skrll }
   1663  1.4.2.2  skrll 
   1664  1.4.2.2  skrll 
   1665  1.4.2.2  skrll /*
   1666  1.4.2.2  skrll  * BTUART H5 Serial Protocol functions.
   1667  1.4.2.2  skrll  */
   1668  1.4.2.2  skrll static int
   1669  1.4.2.2  skrll bth5_enable(device_t self)
   1670  1.4.2.2  skrll {
   1671  1.4.2.2  skrll 	struct bth5_softc *sc = device_private(self);
   1672  1.4.2.2  skrll 	int s;
   1673  1.4.2.2  skrll 
   1674  1.4.2.2  skrll 	if (sc->sc_flags & BTH5_ENABLED)
   1675  1.4.2.2  skrll 		return 0;
   1676  1.4.2.2  skrll 
   1677  1.4.2.2  skrll 	s = spltty();
   1678  1.4.2.2  skrll 
   1679  1.4.2.2  skrll 	sc->sc_flags |= BTH5_ENABLED;
   1680  1.4.2.2  skrll 	sc->sc_flags &= ~BTH5_XMIT;
   1681  1.4.2.2  skrll 
   1682  1.4.2.2  skrll 	splx(s);
   1683  1.4.2.2  skrll 
   1684  1.4.2.2  skrll 	return 0;
   1685  1.4.2.2  skrll }
   1686  1.4.2.2  skrll 
   1687  1.4.2.2  skrll static void
   1688  1.4.2.2  skrll bth5_disable(device_t self)
   1689  1.4.2.2  skrll {
   1690  1.4.2.2  skrll 	struct bth5_softc *sc = device_private(self);
   1691  1.4.2.2  skrll 	int s;
   1692  1.4.2.2  skrll 
   1693  1.4.2.2  skrll 	if ((sc->sc_flags & BTH5_ENABLED) == 0)
   1694  1.4.2.2  skrll 		return;
   1695  1.4.2.2  skrll 
   1696  1.4.2.2  skrll 	s = spltty();
   1697  1.4.2.2  skrll 
   1698  1.4.2.2  skrll 	if (sc->sc_rxp) {
   1699  1.4.2.2  skrll 		m_freem(sc->sc_rxp);
   1700  1.4.2.2  skrll 		sc->sc_rxp = NULL;
   1701  1.4.2.2  skrll 	}
   1702  1.4.2.2  skrll 
   1703  1.4.2.2  skrll 	if (sc->sc_txp) {
   1704  1.4.2.2  skrll 		m_freem(sc->sc_txp);
   1705  1.4.2.2  skrll 		sc->sc_txp = NULL;
   1706  1.4.2.2  skrll 	}
   1707  1.4.2.2  skrll 
   1708  1.4.2.2  skrll 	MBUFQ_DRAIN(&sc->sc_cmdq);
   1709  1.4.2.2  skrll 	MBUFQ_DRAIN(&sc->sc_aclq);
   1710  1.4.2.2  skrll 	MBUFQ_DRAIN(&sc->sc_scoq);
   1711  1.4.2.2  skrll 
   1712  1.4.2.2  skrll 	sc->sc_flags &= ~BTH5_ENABLED;
   1713  1.4.2.2  skrll 	splx(s);
   1714  1.4.2.2  skrll }
   1715  1.4.2.2  skrll 
   1716  1.4.2.2  skrll static void
   1717  1.4.2.2  skrll bth5_start(struct bth5_softc *sc)
   1718  1.4.2.2  skrll {
   1719  1.4.2.2  skrll 	struct mbuf *m;
   1720  1.4.2.2  skrll 
   1721  1.4.2.2  skrll 	KASSERT((sc->sc_flags & BTH5_XMIT) == 0);
   1722  1.4.2.2  skrll 	KASSERT(sc->sc_txp == NULL);
   1723  1.4.2.2  skrll 
   1724  1.4.2.2  skrll 	if (MBUFQ_FIRST(&sc->sc_aclq)) {
   1725  1.4.2.2  skrll 		MBUFQ_DEQUEUE(&sc->sc_aclq, m);
   1726  1.4.2.2  skrll 		sc->sc_stats.acl_tx++;
   1727  1.4.2.2  skrll 		sc->sc_flags |= BTH5_XMIT;
   1728  1.4.2.2  skrll 		bth5_tx_reliable_pkt(sc, m, BTH5_CHANNEL_HCI_ACL);
   1729  1.4.2.2  skrll 	}
   1730  1.4.2.2  skrll 
   1731  1.4.2.2  skrll 	if (MBUFQ_FIRST(&sc->sc_cmdq)) {
   1732  1.4.2.2  skrll 		MBUFQ_DEQUEUE(&sc->sc_cmdq, m);
   1733  1.4.2.2  skrll 		sc->sc_stats.cmd_tx++;
   1734  1.4.2.2  skrll 		sc->sc_flags |= BTH5_XMIT;
   1735  1.4.2.2  skrll 		bth5_tx_reliable_pkt(sc, m, BTH5_CHANNEL_HCI_CMD);
   1736  1.4.2.2  skrll 	}
   1737  1.4.2.2  skrll 
   1738  1.4.2.2  skrll 	if (MBUFQ_FIRST(&sc->sc_scoq)) {
   1739  1.4.2.2  skrll 		MBUFQ_DEQUEUE(&sc->sc_scoq, m);
   1740  1.4.2.2  skrll 		sc->sc_stats.sco_tx++;
   1741  1.4.2.2  skrll 		/* XXXX: We can transmit with reliable */
   1742  1.4.2.2  skrll 		sc->sc_flags |= BTH5_XMIT;
   1743  1.4.2.2  skrll 		bth5_tx_unreliable_pkt(sc, m, BTH5_CHANNEL_HCI_SCO);
   1744  1.4.2.2  skrll 	}
   1745  1.4.2.2  skrll 
   1746  1.4.2.2  skrll 	return;
   1747  1.4.2.2  skrll }
   1748  1.4.2.2  skrll 
   1749  1.4.2.2  skrll static void
   1750  1.4.2.2  skrll bth5_output_cmd(device_t self, struct mbuf *m)
   1751  1.4.2.2  skrll {
   1752  1.4.2.2  skrll 	struct bth5_softc *sc = device_private(self);
   1753  1.4.2.2  skrll 	int s;
   1754  1.4.2.2  skrll 
   1755  1.4.2.2  skrll 	KASSERT(sc->sc_flags & BTH5_ENABLED);
   1756  1.4.2.2  skrll 
   1757  1.4.2.2  skrll 	m_adj(m, sizeof(uint8_t));
   1758  1.4.2.2  skrll 	M_SETCTX(m, NULL);
   1759  1.4.2.2  skrll 
   1760  1.4.2.2  skrll 	s = spltty();
   1761  1.4.2.2  skrll 	MBUFQ_ENQUEUE(&sc->sc_cmdq, m);
   1762  1.4.2.2  skrll 	if ((sc->sc_flags & BTH5_XMIT) == 0)
   1763  1.4.2.2  skrll 		bth5_start(sc);
   1764  1.4.2.2  skrll 
   1765  1.4.2.2  skrll 	splx(s);
   1766  1.4.2.2  skrll }
   1767  1.4.2.2  skrll 
   1768  1.4.2.2  skrll static void
   1769  1.4.2.2  skrll bth5_output_acl(device_t self, struct mbuf *m)
   1770  1.4.2.2  skrll {
   1771  1.4.2.2  skrll 	struct bth5_softc *sc = device_private(self);
   1772  1.4.2.2  skrll 	int s;
   1773  1.4.2.2  skrll 
   1774  1.4.2.2  skrll 	KASSERT(sc->sc_flags & BTH5_ENABLED);
   1775  1.4.2.2  skrll 
   1776  1.4.2.2  skrll 	m_adj(m, sizeof(uint8_t));
   1777  1.4.2.2  skrll 	M_SETCTX(m, NULL);
   1778  1.4.2.2  skrll 
   1779  1.4.2.2  skrll 	s = spltty();
   1780  1.4.2.2  skrll 	MBUFQ_ENQUEUE(&sc->sc_aclq, m);
   1781  1.4.2.2  skrll 	if ((sc->sc_flags & BTH5_XMIT) == 0)
   1782  1.4.2.2  skrll 		bth5_start(sc);
   1783  1.4.2.2  skrll 
   1784  1.4.2.2  skrll 	splx(s);
   1785  1.4.2.2  skrll }
   1786  1.4.2.2  skrll 
   1787  1.4.2.2  skrll static void
   1788  1.4.2.2  skrll bth5_output_sco(device_t self, struct mbuf *m)
   1789  1.4.2.2  skrll {
   1790  1.4.2.2  skrll 	struct bth5_softc *sc = device_private(self);
   1791  1.4.2.2  skrll 	int s;
   1792  1.4.2.2  skrll 
   1793  1.4.2.2  skrll 	KASSERT(sc->sc_flags & BTH5_ENABLED);
   1794  1.4.2.2  skrll 
   1795  1.4.2.2  skrll 	m_adj(m, sizeof(uint8_t));
   1796  1.4.2.2  skrll 
   1797  1.4.2.2  skrll 	s = spltty();
   1798  1.4.2.2  skrll 	MBUFQ_ENQUEUE(&sc->sc_scoq, m);
   1799  1.4.2.2  skrll 	if ((sc->sc_flags & BTH5_XMIT) == 0)
   1800  1.4.2.2  skrll 		bth5_start(sc);
   1801  1.4.2.2  skrll 
   1802  1.4.2.2  skrll 	splx(s);
   1803  1.4.2.2  skrll }
   1804  1.4.2.2  skrll 
   1805  1.4.2.2  skrll static void
   1806  1.4.2.2  skrll bth5_stats(device_t self, struct bt_stats *dest, int flush)
   1807  1.4.2.2  skrll {
   1808  1.4.2.2  skrll 	struct bth5_softc *sc = device_private(self);
   1809  1.4.2.2  skrll 	int s;
   1810  1.4.2.2  skrll 
   1811  1.4.2.2  skrll 	s = spltty();
   1812  1.4.2.2  skrll 	memcpy(dest, &sc->sc_stats, sizeof(struct bt_stats));
   1813  1.4.2.2  skrll 
   1814  1.4.2.2  skrll 	if (flush)
   1815  1.4.2.2  skrll 		memset(&sc->sc_stats, 0, sizeof(struct bt_stats));
   1816  1.4.2.2  skrll 
   1817  1.4.2.2  skrll 	splx(s);
   1818  1.4.2.2  skrll }
   1819  1.4.2.2  skrll 
   1820  1.4.2.2  skrll 
   1821  1.4.2.2  skrll #ifdef BTH5_DEBUG
   1822  1.4.2.2  skrll static void
   1823  1.4.2.2  skrll bth5_packet_print(struct mbuf *m)
   1824  1.4.2.2  skrll {
   1825  1.4.2.2  skrll 	int i;
   1826  1.4.2.2  skrll 	uint8_t *p;
   1827  1.4.2.2  skrll 
   1828  1.4.2.2  skrll 	for ( ; m != NULL; m = m->m_next) {
   1829  1.4.2.2  skrll 		p = mtod(m, uint8_t *);
   1830  1.4.2.2  skrll 		for (i = 0; i < m->m_len; i++) {
   1831  1.4.2.2  skrll 			if (i % 16 == 0)
   1832  1.4.2.2  skrll 				printf(" ");
   1833  1.4.2.2  skrll 			printf(" %02x", *(p + i));
   1834  1.4.2.2  skrll 			if (i % 16 == 15)
   1835  1.4.2.2  skrll 				printf("\n");
   1836  1.4.2.2  skrll 		}
   1837  1.4.2.2  skrll 		printf("\n");
   1838  1.4.2.2  skrll 	}
   1839  1.4.2.2  skrll }
   1840  1.4.2.2  skrll #endif
   1841