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