Home | History | Annotate | Line # | Download | only in bluetooth
bth5.c revision 1.6
      1  1.6  mlelstv /*	$NetBSD: bth5.c,v 1.6 2019/11/16 22:06:49 mlelstv 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.6  mlelstv __KERNEL_RCSID(0, "$NetBSD: bth5.c,v 1.6 2019/11/16 22:06:49 mlelstv 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 	KASSERT(tp->t_oproc != NULL);
    396  1.1      nat 
    397  1.1      nat 	cfdata = malloc(sizeof(struct cfdata), M_DEVBUF, M_WAITOK);
    398  1.1      nat 	for (unit = 0; unit < bthfive_cd.cd_ndevs; unit++)
    399  1.1      nat 		if (device_lookup(&bthfive_cd, unit) == NULL)
    400  1.1      nat 			break;
    401  1.1      nat 	cfdata->cf_name = name;
    402  1.1      nat 	cfdata->cf_atname = name;
    403  1.1      nat 	cfdata->cf_unit = unit;
    404  1.1      nat 	cfdata->cf_fstate = FSTATE_STAR;
    405  1.1      nat 
    406  1.1      nat 	aprint_normal("%s%d at tty major %llu minor %llu",
    407  1.1      nat 	    name, unit, (unsigned long long)major(tp->t_dev),
    408  1.1      nat 	    (unsigned long long)minor(tp->t_dev));
    409  1.1      nat 	dev = config_attach_pseudo(cfdata);
    410  1.1      nat 	if (dev == NULL) {
    411  1.1      nat 		splx(s);
    412  1.1      nat 		return EIO;
    413  1.1      nat 	}
    414  1.1      nat 	sc = device_private(dev);
    415  1.1      nat 
    416  1.1      nat 	mutex_spin_enter(&tty_lock);
    417  1.1      nat 	tp->t_sc = sc;
    418  1.1      nat 	sc->sc_tp = tp;
    419  1.1      nat 	ttyflush(tp, FREAD | FWRITE);
    420  1.1      nat 	mutex_spin_exit(&tty_lock);
    421  1.1      nat 
    422  1.1      nat 	splx(s);
    423  1.1      nat 
    424  1.1      nat 	sc->sc_slip_txrsv = BTH5_SLIP_PKTSTART;
    425  1.1      nat 	bth5_sequencing_reset(sc);
    426  1.1      nat 
    427  1.1      nat 	/* start link-establishment */
    428  1.1      nat 	bth5_start_le(sc);
    429  1.1      nat 
    430  1.1      nat 	return 0;
    431  1.1      nat }
    432  1.1      nat 
    433  1.1      nat /* ARGSUSED */
    434  1.1      nat static int
    435  1.1      nat bth5close(struct tty *tp, int flag __unused)
    436  1.1      nat {
    437  1.1      nat 	struct bth5_softc *sc = tp->t_sc;
    438  1.1      nat 	cfdata_t cfdata;
    439  1.1      nat 	int s;
    440  1.1      nat 
    441  1.1      nat 	/* terminate link-establishment */
    442  1.1      nat 	bth5_terminate_le(sc);
    443  1.1      nat 
    444  1.1      nat 	s = spltty();
    445  1.1      nat 
    446  1.1      nat 	MBUFQ_DRAIN(&sc->sc_dgq);
    447  1.1      nat 	bth5_sequencing_reset(sc);
    448  1.1      nat 
    449  1.1      nat 	mutex_spin_enter(&tty_lock);
    450  1.1      nat 	ttyflush(tp, FREAD | FWRITE);
    451  1.1      nat 	mutex_spin_exit(&tty_lock);	/* XXX */
    452  1.1      nat 	ttyldisc_release(tp->t_linesw);
    453  1.1      nat 	tp->t_linesw = ttyldisc_default();
    454  1.1      nat 	if (sc != NULL) {
    455  1.1      nat 		tp->t_sc = NULL;
    456  1.1      nat 		if (sc->sc_tp == tp) {
    457  1.1      nat 			cfdata = device_cfdata(sc->sc_dev);
    458  1.1      nat 			config_detach(sc->sc_dev, 0);
    459  1.1      nat 			free(cfdata, M_DEVBUF);
    460  1.1      nat 		}
    461  1.1      nat 
    462  1.1      nat 	}
    463  1.1      nat 	splx(s);
    464  1.1      nat 	return 0;
    465  1.1      nat }
    466  1.1      nat 
    467  1.1      nat /* ARGSUSED */
    468  1.1      nat static int
    469  1.1      nat bth5ioctl(struct tty *tp, u_long cmd, void *data, int flag __unused,
    470  1.1      nat 	  struct lwp *l __unused)
    471  1.1      nat {
    472  1.1      nat 	struct bth5_softc *sc = tp->t_sc;
    473  1.1      nat 	int error;
    474  1.1      nat 
    475  1.1      nat 	if (sc == NULL || tp != sc->sc_tp)
    476  1.1      nat 		return EPASSTHROUGH;
    477  1.1      nat 
    478  1.1      nat 	error = 0;
    479  1.1      nat 	switch (cmd) {
    480  1.1      nat 	default:
    481  1.1      nat 		error = EPASSTHROUGH;
    482  1.1      nat 		break;
    483  1.1      nat 	}
    484  1.1      nat 
    485  1.1      nat 	return error;
    486  1.1      nat }
    487  1.1      nat 
    488  1.1      nat 
    489  1.1      nat /*
    490  1.1      nat  * UART Driver Layer is supported by com-driver.
    491  1.1      nat  */
    492  1.1      nat 
    493  1.1      nat /*
    494  1.1      nat  * BTH5 SLIP Layer functions:
    495  1.1      nat  *   Supports to transmit/receive a byte stream.
    496  1.1      nat  *   SLIP protocol described in Internet standard RFC 1055.
    497  1.1      nat  */
    498  1.1      nat static int
    499  1.1      nat bth5_slip_transmit(struct tty *tp)
    500  1.1      nat {
    501  1.1      nat 	struct bth5_softc *sc = tp->t_sc;
    502  1.1      nat 	struct mbuf *m;
    503  1.1      nat 	int count, rlen;
    504  1.1      nat 	uint8_t *rptr;
    505  1.5      nat 	int s;
    506  1.1      nat 
    507  1.1      nat 	m = sc->sc_txp;
    508  1.1      nat 	if (m == NULL) {
    509  1.5      nat 		s = spltty();
    510  1.1      nat 		sc->sc_flags &= ~BTH5_XMIT;
    511  1.5      nat 		splx(s);
    512  1.1      nat 		bth5_mux_transmit(sc);
    513  1.1      nat 		return 0;
    514  1.1      nat 	}
    515  1.1      nat 
    516  1.1      nat 	count = 0;
    517  1.1      nat 	rlen = 0;
    518  1.1      nat 	rptr = mtod(m, uint8_t *);
    519  1.1      nat 
    520  1.1      nat 	if (sc->sc_slip_txrsv != 0) {
    521  1.1      nat #ifdef BTH5_DEBUG
    522  1.1      nat 		if (sc->sc_slip_txrsv == BTH5_SLIP_PKTSTART)
    523  1.1      nat 			DPRINTFN(4, ("%s: slip transmit start\n",
    524  1.1      nat 			    device_xname(sc->sc_dev)));
    525  1.1      nat 		else
    526  1.1      nat 			DPRINTFN(4, ("0x%02x ", sc->sc_slip_txrsv));
    527  1.1      nat #endif
    528  1.1      nat 
    529  1.1      nat 		if (putc(sc->sc_slip_txrsv, &tp->t_outq) < 0)
    530  1.1      nat 			return 0;
    531  1.1      nat 		count++;
    532  1.1      nat 
    533  1.1      nat 		if (sc->sc_slip_txrsv == BTH5_SLIP_ESCAPE_PKTEND ||
    534  1.1      nat 		    sc->sc_slip_txrsv == BTH5_SLIP_ESCAPE_ESCAPE) {
    535  1.1      nat 			rlen++;
    536  1.1      nat 			rptr++;
    537  1.1      nat 		}
    538  1.5      nat 		if (sc->sc_oof_flow_control == true) {
    539  1.5      nat 			if (sc->sc_slip_txrsv == BTH5_SLIP_ESCAPE_XON ||
    540  1.5      nat 			    sc->sc_slip_txrsv == BTH5_SLIP_ESCAPE_XOFF) {
    541  1.5      nat 				rlen++;
    542  1.5      nat 				rptr++;
    543  1.5      nat 			}
    544  1.5      nat 		}
    545  1.5      nat 
    546  1.1      nat 		sc->sc_slip_txrsv = 0;
    547  1.1      nat 	}
    548  1.1      nat 
    549  1.1      nat 	for(;;) {
    550  1.1      nat 		if (rlen >= m->m_len) {
    551  1.1      nat 			m = m->m_next;
    552  1.1      nat 			if (m == NULL) {
    553  1.1      nat 				if (putc(BTH5_SLIP_PKTEND, &tp->t_outq) < 0)
    554  1.1      nat 					break;
    555  1.1      nat 
    556  1.1      nat 				DPRINTFN(4, ("\n%s: slip transmit end\n",
    557  1.1      nat 				    device_xname(sc->sc_dev)));
    558  1.1      nat 
    559  1.1      nat 				m = sc->sc_txp;
    560  1.1      nat 				sc->sc_txp = NULL;
    561  1.1      nat 				sc->sc_slip_txrsv = BTH5_SLIP_PKTSTART;
    562  1.1      nat 
    563  1.1      nat 				sc->sc_transmit_callback(sc, m);
    564  1.1      nat 				m = NULL;
    565  1.1      nat 				break;
    566  1.1      nat 			}
    567  1.1      nat 
    568  1.1      nat 			rlen = 0;
    569  1.1      nat 			rptr = mtod(m, uint8_t *);
    570  1.1      nat 			continue;
    571  1.1      nat 		}
    572  1.1      nat 
    573  1.1      nat 		if (*rptr == BTH5_SLIP_PKTEND) {
    574  1.1      nat 			if (putc(BTH5_SLIP_ESCAPE, &tp->t_outq) < 0)
    575  1.1      nat 				break;
    576  1.1      nat 			count++;
    577  1.1      nat 			DPRINTFN(4, (" esc "));
    578  1.1      nat 
    579  1.1      nat 			if (putc(BTH5_SLIP_ESCAPE_PKTEND, &tp->t_outq) < 0) {
    580  1.1      nat 				sc->sc_slip_txrsv = BTH5_SLIP_ESCAPE_PKTEND;
    581  1.1      nat 				break;
    582  1.1      nat 			}
    583  1.1      nat 			DPRINTFN(4, ("0x%02x ", BTH5_SLIP_ESCAPE_PKTEND));
    584  1.1      nat 			rptr++;
    585  1.5      nat 		} else if (sc->sc_oof_flow_control == true && *rptr ==
    586  1.5      nat 							 BTH5_SLIP_XON) {
    587  1.1      nat 			if (putc(BTH5_SLIP_ESCAPE, &tp->t_outq) < 0)
    588  1.1      nat 				break;
    589  1.1      nat 			count++;
    590  1.1      nat 			DPRINTFN(4, (" esc "));
    591  1.1      nat 
    592  1.1      nat 			if (putc(BTH5_SLIP_ESCAPE_XON, &tp->t_outq) < 0) {
    593  1.1      nat 				sc->sc_slip_txrsv = BTH5_SLIP_ESCAPE_XON;
    594  1.1      nat 				break;
    595  1.1      nat 			}
    596  1.1      nat 			DPRINTFN(4, ("0x%02x ", BTH5_SLIP_ESCAPE_XON));
    597  1.1      nat 			rptr++;
    598  1.5      nat 		} else if (sc->sc_oof_flow_control == true && *rptr ==
    599  1.5      nat 							 BTH5_SLIP_XOFF) {
    600  1.1      nat 			if (putc(BTH5_SLIP_ESCAPE, &tp->t_outq) < 0)
    601  1.1      nat 				break;
    602  1.1      nat 			count++;
    603  1.1      nat 			DPRINTFN(4, (" esc "));
    604  1.1      nat 
    605  1.1      nat 			if (putc(BTH5_SLIP_ESCAPE_XOFF, &tp->t_outq) < 0) {
    606  1.1      nat 				sc->sc_slip_txrsv = BTH5_SLIP_ESCAPE_XOFF;
    607  1.1      nat 				break;
    608  1.1      nat 			}
    609  1.1      nat 			DPRINTFN(4, ("0x%02x ", BTH5_SLIP_ESCAPE_XOFF));
    610  1.1      nat 			rptr++;
    611  1.1      nat 		} else if (*rptr == BTH5_SLIP_ESCAPE) {
    612  1.1      nat 			if (putc(BTH5_SLIP_ESCAPE, &tp->t_outq) < 0)
    613  1.1      nat 				break;
    614  1.1      nat 			count++;
    615  1.1      nat 			DPRINTFN(4, (" esc "));
    616  1.1      nat 
    617  1.1      nat 			if (putc(BTH5_SLIP_ESCAPE_ESCAPE, &tp->t_outq) < 0) {
    618  1.1      nat 				sc->sc_slip_txrsv = BTH5_SLIP_ESCAPE_ESCAPE;
    619  1.1      nat 				break;
    620  1.1      nat 			}
    621  1.1      nat 			DPRINTFN(4, ("0x%02x ", BTH5_SLIP_ESCAPE_ESCAPE));
    622  1.1      nat 			rptr++;
    623  1.1      nat 		} else {
    624  1.1      nat 			if (putc(*rptr++, &tp->t_outq) < 0)
    625  1.1      nat 				break;
    626  1.1      nat 			DPRINTFN(4, ("0x%02x ", *(rptr - 1)));
    627  1.1      nat 		}
    628  1.1      nat 		rlen++;
    629  1.1      nat 		count++;
    630  1.1      nat 	}
    631  1.1      nat 	if (m != NULL)
    632  1.1      nat 		m_adj(m, rlen);
    633  1.1      nat 
    634  1.1      nat 	sc->sc_stats.byte_tx += count;
    635  1.1      nat 
    636  1.1      nat 	if (tp->t_outq.c_cc != 0)
    637  1.1      nat 		(*tp->t_oproc)(tp);
    638  1.1      nat 
    639  1.1      nat 	return 0;
    640  1.1      nat }
    641  1.1      nat 
    642  1.1      nat static int
    643  1.1      nat bth5_slip_receive(int c, struct tty *tp)
    644  1.1      nat {
    645  1.1      nat 	struct bth5_softc *sc = tp->t_sc;
    646  1.1      nat 	struct mbuf *m = sc->sc_rxp;
    647  1.1      nat 	int discard = 0;
    648  1.1      nat 	const char *errstr;
    649  1.1      nat 
    650  1.1      nat 	c &= TTY_CHARMASK;
    651  1.1      nat 
    652  1.1      nat 	/* If we already started a packet, find the trailing end of it. */
    653  1.1      nat 	if (m) {
    654  1.1      nat 		while (m->m_next)
    655  1.1      nat 			m = m->m_next;
    656  1.1      nat 
    657  1.1      nat 		if (M_TRAILINGSPACE(m) == 0) {
    658  1.1      nat 			/* extend mbuf */
    659  1.1      nat 			MGET(m->m_next, M_DONTWAIT, MT_DATA);
    660  1.1      nat 			if (m->m_next == NULL) {
    661  1.1      nat 				aprint_error_dev(sc->sc_dev,
    662  1.1      nat 				    "out of memory\n");
    663  1.1      nat 				sc->sc_stats.err_rx++;
    664  1.1      nat 				return 0;	/* (lost sync) */
    665  1.1      nat 			}
    666  1.1      nat 
    667  1.1      nat 			m = m->m_next;
    668  1.1      nat 			m->m_len = 0;
    669  1.1      nat 		}
    670  1.1      nat 	} else
    671  1.1      nat 		if (c != BTH5_SLIP_PKTSTART) {
    672  1.1      nat 			discard = 1;
    673  1.1      nat 			errstr = "not sync";
    674  1.1      nat 			goto discarded;
    675  1.1      nat 		}
    676  1.1      nat 
    677  1.1      nat 	switch (c) {
    678  1.1      nat 	case BTH5_SLIP_PKTSTART /* or _PKTEND */:
    679  1.1      nat 		if (m == NULL) {
    680  1.1      nat 			/* BTH5_SLIP_PKTSTART */
    681  1.1      nat 
    682  1.1      nat 			DPRINTFN(4, ("%s: slip receive start\n",
    683  1.1      nat 			    device_xname(sc->sc_dev)));
    684  1.1      nat 
    685  1.1      nat 			/* new packet */
    686  1.1      nat 			MGETHDR(m, M_DONTWAIT, MT_DATA);
    687  1.1      nat 			if (m == NULL) {
    688  1.1      nat 				aprint_error_dev(sc->sc_dev,
    689  1.1      nat 				    "out of memory\n");
    690  1.1      nat 				sc->sc_stats.err_rx++;
    691  1.1      nat 				return 0;	/* (lost sync) */
    692  1.1      nat 			}
    693  1.1      nat 
    694  1.1      nat 			sc->sc_rxp = m;
    695  1.1      nat 			m->m_pkthdr.len = m->m_len = 0;
    696  1.1      nat 			sc->sc_slip_rxexp = 0;
    697  1.1      nat 		} else {
    698  1.1      nat 			/* BTH5_SLIP_PKTEND */
    699  1.1      nat 
    700  1.1      nat 			if (m == sc->sc_rxp && m->m_len == 0) {
    701  1.1      nat 				DPRINTFN(4, ("%s: resynchronises\n",
    702  1.1      nat 				    device_xname(sc->sc_dev)));
    703  1.1      nat 
    704  1.1      nat 				sc->sc_stats.byte_rx++;
    705  1.1      nat 				return 0;
    706  1.1      nat 			}
    707  1.1      nat 
    708  1.1      nat 			DPRINTFN(4, ("%s%s: slip receive end\n",
    709  1.1      nat 			    (m->m_len % 16 != 0) ? "\n" :  "",
    710  1.1      nat 			    device_xname(sc->sc_dev)));
    711  1.1      nat 
    712  1.1      nat 			bth5_pktintegrity_receive(sc, sc->sc_rxp);
    713  1.1      nat 			sc->sc_rxp = NULL;
    714  1.1      nat 			sc->sc_slip_rxexp = BTH5_SLIP_PKTSTART;
    715  1.1      nat 		}
    716  1.1      nat 		sc->sc_stats.byte_rx++;
    717  1.1      nat 		return 0;
    718  1.1      nat 
    719  1.1      nat 	case BTH5_SLIP_ESCAPE:
    720  1.1      nat 
    721  1.1      nat 		DPRINTFN(4, ("  esc"));
    722  1.1      nat 
    723  1.1      nat 		if (sc->sc_slip_rxexp == BTH5_SLIP_ESCAPE) {
    724  1.1      nat 			discard = 1;
    725  1.1      nat 			errstr = "waiting 0xdc or 0xdb or 0xde of 0xdf";
    726  1.1      nat 		} else
    727  1.1      nat 			sc->sc_slip_rxexp = BTH5_SLIP_ESCAPE;
    728  1.1      nat 		break;
    729  1.1      nat 
    730  1.1      nat 	default:
    731  1.1      nat 		DPRINTFN(4, (" 0x%02x%s",
    732  1.1      nat 		    c, (m->m_len % 16 == 15) ? "\n" :  ""));
    733  1.1      nat 
    734  1.1      nat 		switch (sc->sc_slip_rxexp) {
    735  1.1      nat 		case BTH5_SLIP_PKTSTART:
    736  1.1      nat 			discard = 1;
    737  1.1      nat 			errstr = "waiting 0xc0";
    738  1.1      nat 			break;
    739  1.1      nat 
    740  1.1      nat 		case BTH5_SLIP_ESCAPE:
    741  1.1      nat 			if (c == BTH5_SLIP_ESCAPE_PKTEND)
    742  1.1      nat 				mtod(m, uint8_t *)[m->m_len++] =
    743  1.1      nat 				    BTH5_SLIP_PKTEND;
    744  1.5      nat 			else if (sc->sc_oof_flow_control == true &&
    745  1.5      nat 						c == BTH5_SLIP_ESCAPE_XON)
    746  1.1      nat 				mtod(m, uint8_t *)[m->m_len++] =
    747  1.1      nat 				    BTH5_SLIP_XON;
    748  1.5      nat 			else if (sc->sc_oof_flow_control == true &&
    749  1.5      nat 						c == BTH5_SLIP_ESCAPE_XOFF)
    750  1.1      nat 				mtod(m, uint8_t *)[m->m_len++] =
    751  1.1      nat 				    BTH5_SLIP_XOFF;
    752  1.1      nat 			else if (c == BTH5_SLIP_ESCAPE_ESCAPE)
    753  1.1      nat 				mtod(m, uint8_t *)[m->m_len++] =
    754  1.1      nat 				    BTH5_SLIP_ESCAPE;
    755  1.1      nat 			else {
    756  1.1      nat 				discard = 1;
    757  1.1      nat 				errstr = "unknown escape";
    758  1.1      nat 			}
    759  1.1      nat 			sc->sc_slip_rxexp = 0;
    760  1.1      nat 			break;
    761  1.1      nat 
    762  1.1      nat 		default:
    763  1.1      nat 			mtod(m, uint8_t *)[m->m_len++] = c;
    764  1.1      nat 		}
    765  1.1      nat 		sc->sc_rxp->m_pkthdr.len++;
    766  1.1      nat 	}
    767  1.1      nat 	if (discard) {
    768  1.1      nat discarded:
    769  1.1      nat #ifdef BTH5_DEBUG
    770  1.1      nat 		DPRINTFN(4, ("%s: receives unexpected byte 0x%02x: %s\n",
    771  1.1      nat 		    device_xname(sc->sc_dev), c, errstr));
    772  1.1      nat #else
    773  1.1      nat 		__USE(errstr);
    774  1.1      nat #endif
    775  1.1      nat 	}
    776  1.1      nat 	sc->sc_stats.byte_rx++;
    777  1.1      nat 
    778  1.1      nat 	return 0;
    779  1.1      nat }
    780  1.1      nat 
    781  1.1      nat 
    782  1.1      nat /*
    783  1.1      nat  * BTH5 Packet Integrity Layer functions:
    784  1.1      nat  *   handling Payload Length, Checksum, CRC.
    785  1.1      nat  */
    786  1.1      nat static void
    787  1.1      nat bth5_pktintegrity_transmit(struct bth5_softc *sc)
    788  1.1      nat {
    789  1.1      nat 	struct mbuf *m = sc->sc_txp;
    790  1.1      nat 	bth5_hdr_t *hdrp = mtod(m, bth5_hdr_t *);
    791  1.1      nat 	int pldlen;
    792  1.1      nat 
    793  1.1      nat 	DPRINTFN(3, ("%s: pi transmit\n", device_xname(sc->sc_dev)));
    794  1.1      nat 
    795  1.1      nat 	pldlen = m->m_pkthdr.len - sizeof(bth5_hdr_t);
    796  1.1      nat 
    797  1.1      nat 	if (sc->sc_pi_txcrc)
    798  1.1      nat 		hdrp->flags |= BTH5_FLAGS_CRC_PRESENT;
    799  1.1      nat 
    800  1.1      nat 	BTH5_SET_PLEN(hdrp, pldlen);
    801  1.1      nat 	BTH5_SET_CSUM(hdrp);
    802  1.1      nat 
    803  1.1      nat 	if (sc->sc_pi_txcrc) {
    804  1.1      nat 		struct mbuf *_m;
    805  1.1      nat 		int n = 0;
    806  1.1      nat 		uint16_t crc = 0xffff;
    807  1.1      nat 		uint8_t *buf;
    808  1.1      nat 
    809  1.1      nat 		for (_m = m; _m != NULL; _m = _m->m_next) {
    810  1.1      nat 			buf = mtod(_m, uint8_t *);
    811  1.1      nat 			for (n = 0; n < _m->m_len; n++)
    812  1.1      nat 				bth5_crc_update(&crc, *(buf + n));
    813  1.1      nat 		}
    814  1.1      nat 		crc = htobe16(bth5_crc_reverse(crc));
    815  1.1      nat 		m_copyback(m, m->m_pkthdr.len, sizeof(crc), &crc);
    816  1.1      nat 	}
    817  1.1      nat 
    818  1.1      nat #ifdef BTH5_DEBUG
    819  1.1      nat 	if (bth5_debug == 3)
    820  1.1      nat 		bth5_packet_print(m);
    821  1.1      nat #endif
    822  1.1      nat 
    823  1.1      nat 	bth5_slip_transmit(sc->sc_tp);
    824  1.1      nat }
    825  1.1      nat 
    826  1.1      nat static void
    827  1.1      nat bth5_pktintegrity_receive(struct bth5_softc *sc, struct mbuf *m)
    828  1.1      nat {
    829  1.1      nat 	bth5_hdr_t *hdrp = mtod(m, bth5_hdr_t *);
    830  1.1      nat 	u_int pldlen;
    831  1.1      nat 	int discard = 0;
    832  1.1      nat 	uint16_t crc = 0xffff;
    833  1.1      nat 	const char *errstr;
    834  1.1      nat 
    835  1.1      nat 	DPRINTFN(3, ("%s: pi receive\n", device_xname(sc->sc_dev)));
    836  1.1      nat #ifdef BTH5_DEBUG
    837  1.1      nat 	if (bth5_debug == 4)
    838  1.1      nat 		bth5_packet_print(m);
    839  1.1      nat #endif
    840  1.1      nat 
    841  1.1      nat 	KASSERT(m->m_len >= sizeof(bth5_hdr_t));
    842  1.1      nat 
    843  1.1      nat 	pldlen = m->m_pkthdr.len - sizeof(bth5_hdr_t) -
    844  1.1      nat 	    ((hdrp->flags & BTH5_FLAGS_CRC_PRESENT) ? sizeof(crc) : 0);
    845  1.1      nat 	if (pldlen > 0xfff) {
    846  1.1      nat 		discard = 1;
    847  1.1      nat 		errstr = "Payload Length";
    848  1.1      nat 		goto discarded;
    849  1.1      nat 	}
    850  1.1      nat 	if (hdrp->csum != BTH5_GET_CSUM(hdrp)) {
    851  1.1      nat 		discard = 1;
    852  1.1      nat 		errstr = "Checksum";
    853  1.1      nat 		goto discarded;
    854  1.1      nat 	}
    855  1.1      nat 	if (BTH5_GET_PLEN(hdrp) != pldlen) {
    856  1.1      nat 		discard = 1;
    857  1.1      nat 		errstr = "Payload Length";
    858  1.1      nat 		goto discarded;
    859  1.1      nat 	}
    860  1.1      nat 	if (hdrp->flags & BTH5_FLAGS_CRC_PRESENT) {
    861  1.1      nat 		struct mbuf *_m;
    862  1.1      nat 		int i, n;
    863  1.1      nat 		uint16_t crc0;
    864  1.1      nat 		uint8_t *buf;
    865  1.1      nat 
    866  1.1      nat 		i = 0;
    867  1.1      nat 		n = 0;
    868  1.1      nat 		for (_m = m; _m != NULL; _m = _m->m_next) {
    869  1.1      nat 			buf = mtod(m, uint8_t *);
    870  1.1      nat 			for (n = 0;
    871  1.1      nat 			    n < _m->m_len && i < sizeof(bth5_hdr_t) + pldlen;
    872  1.1      nat 			    n++, i++)
    873  1.1      nat 				bth5_crc_update(&crc, *(buf + n));
    874  1.1      nat 		}
    875  1.1      nat 
    876  1.1      nat 		m_copydata(_m, n, sizeof(crc0), &crc0);
    877  1.1      nat 		if (be16toh(crc0) != bth5_crc_reverse(crc)) {
    878  1.1      nat 			discard = 1;
    879  1.1      nat 			errstr = "CRC";
    880  1.1      nat 		} else
    881  1.1      nat 			/* Shaves CRC */
    882  1.1      nat 			m_adj(m, (int)(0 - sizeof(crc)));
    883  1.1      nat 	}
    884  1.1      nat 
    885  1.1      nat 	if (discard) {
    886  1.1      nat discarded:
    887  1.1      nat #ifdef BTH5_DEBUG
    888  1.1      nat 		DPRINTFN(3, ("%s: receives unexpected packet: %s\n",
    889  1.1      nat 		    device_xname(sc->sc_dev), errstr));
    890  1.1      nat #else
    891  1.1      nat 		__USE(errstr);
    892  1.1      nat #endif
    893  1.1      nat 		m_freem(m);
    894  1.1      nat 	} else
    895  1.1      nat 		bth5_mux_receive(sc, m);
    896  1.1      nat }
    897  1.1      nat 
    898  1.1      nat static const uint16_t crctbl[] = {
    899  1.1      nat 	0x0000, 0x1081, 0x2102, 0x3183,
    900  1.1      nat 	0x4204, 0x5285, 0x6306, 0x7387,
    901  1.1      nat 	0x8408, 0x9489, 0xa50a, 0xb58b,
    902  1.1      nat 	0xc60c, 0xd68d, 0xe70e, 0xf78f,
    903  1.1      nat };
    904  1.1      nat 
    905  1.1      nat static void
    906  1.1      nat bth5_crc_update(uint16_t *crc, uint8_t d)
    907  1.1      nat {
    908  1.1      nat 	uint16_t reg = *crc;
    909  1.1      nat 
    910  1.1      nat 	reg = (reg >> 4) ^ crctbl[(reg ^ d) & 0x000f];
    911  1.1      nat 	reg = (reg >> 4) ^ crctbl[(reg ^ (d >> 4)) & 0x000f];
    912  1.1      nat 
    913  1.1      nat 	*crc = reg;
    914  1.1      nat }
    915  1.1      nat 
    916  1.1      nat static uint16_t
    917  1.1      nat bth5_crc_reverse(uint16_t crc)
    918  1.1      nat {
    919  1.1      nat 	uint16_t b, rev;
    920  1.1      nat 
    921  1.1      nat 	for (b = 0, rev = 0; b < 16; b++) {
    922  1.1      nat 		rev = rev << 1;
    923  1.1      nat 		rev |= (crc & 1);
    924  1.1      nat 		crc = crc >> 1;
    925  1.1      nat 	}
    926  1.1      nat 
    927  1.1      nat 	return rev;
    928  1.1      nat }
    929  1.1      nat 
    930  1.1      nat 
    931  1.1      nat /*
    932  1.1      nat  * BTH5 MUX Layer functions
    933  1.1      nat  */
    934  1.1      nat static void
    935  1.1      nat bth5_mux_transmit(struct bth5_softc *sc)
    936  1.1      nat {
    937  1.1      nat 	struct mbuf *m;
    938  1.1      nat 	bth5_hdr_t *hdrp;
    939  1.5      nat 	int s;
    940  1.1      nat 
    941  1.1      nat 	DPRINTFN(2, ("%s: mux transmit: sc_flags=0x%x, choke=%d",
    942  1.1      nat 	    device_xname(sc->sc_dev), sc->sc_flags, sc->sc_mux_choke));
    943  1.1      nat 
    944  1.1      nat 	if (sc->sc_mux_choke) {
    945  1.1      nat 		struct mbuf *_m = NULL;
    946  1.1      nat 
    947  1.1      nat 		/* In this case, send only Link Establishment packet */
    948  1.1      nat 		for (m = MBUFQ_FIRST(&sc->sc_dgq); m != NULL;
    949  1.1      nat 		    _m = m, m = MBUFQ_NEXT(m)) {
    950  1.1      nat 			hdrp = mtod(m, bth5_hdr_t *);
    951  1.1      nat 			if (hdrp->ident == BTH5_CHANNEL_LE) {
    952  1.1      nat 				if (m == MBUFQ_FIRST(&sc->sc_dgq))
    953  1.1      nat 					MBUFQ_DEQUEUE(&sc->sc_dgq, m);
    954  1.1      nat 				else {
    955  1.1      nat 					if (m->m_nextpkt == NULL)
    956  1.1      nat 						sc->sc_dgq.mq_last =
    957  1.1      nat 						    &_m->m_nextpkt;
    958  1.1      nat 					_m->m_nextpkt = m->m_nextpkt;
    959  1.1      nat 					m->m_nextpkt = NULL;
    960  1.1      nat 				}
    961  1.1      nat 				goto transmit;
    962  1.1      nat 			}
    963  1.1      nat 		}
    964  1.1      nat 		DPRINTFN(2, ("\n"));
    965  1.1      nat 		return;
    966  1.1      nat 	}
    967  1.1      nat 
    968  1.1      nat 	/*
    969  1.1      nat 	 * The MUX Layer always gives priority to packets from the Datagram
    970  1.1      nat 	 * Queue Layer over the Sequencing Layer.
    971  1.1      nat 	 */
    972  1.1      nat 	if (MBUFQ_FIRST(&sc->sc_dgq)) {
    973  1.1      nat 		MBUFQ_DEQUEUE(&sc->sc_dgq, m);
    974  1.1      nat 		goto transmit;
    975  1.1      nat 	}
    976  1.1      nat 	if (MBUFQ_FIRST(&sc->sc_seqq)) {
    977  1.1      nat 		MBUFQ_DEQUEUE(&sc->sc_seqq, m);
    978  1.1      nat 		hdrp = mtod(m, bth5_hdr_t *);
    979  1.1      nat 		hdrp->flags |= BTH5_FLAGS_PROTOCOL_REL;		/* Reliable */
    980  1.1      nat 		goto transmit;
    981  1.1      nat 	}
    982  1.5      nat 
    983  1.5      nat 	s = spltty();
    984  1.5      nat 	if ((sc->sc_flags & BTH5_XMIT) == 0)
    985  1.5      nat 		bth5_start(sc);
    986  1.5      nat 	splx(s);
    987  1.5      nat 
    988  1.1      nat 	if (sc->sc_mux_send_ack == true) {
    989  1.1      nat 		m = bth5_create_ackpkt();
    990  1.1      nat 		if (m != NULL)
    991  1.1      nat 			goto transmit;
    992  1.1      nat 		aprint_error_dev(sc->sc_dev, "out of memory\n");
    993  1.1      nat 		sc->sc_stats.err_tx++;
    994  1.1      nat 	}
    995  1.1      nat 
    996  1.1      nat 	/* Nothing to send */
    997  1.1      nat 	DPRINTFN(2, ("\n"));
    998  1.5      nat 
    999  1.1      nat 	return;
   1000  1.1      nat 
   1001  1.1      nat transmit:
   1002  1.1      nat 	DPRINTFN(2, (", txack=%d, send_ack=%d\n",
   1003  1.1      nat 	    bth5_get_txack(sc), sc->sc_mux_send_ack));
   1004  1.1      nat 
   1005  1.1      nat 	hdrp = mtod(m, bth5_hdr_t *);
   1006  1.1      nat 	hdrp->flags |=
   1007  1.1      nat 	    (bth5_get_txack(sc) << BTH5_FLAGS_ACK_SHIFT) & BTH5_FLAGS_ACK_MASK;
   1008  1.1      nat 	if (sc->sc_mux_send_ack == true)
   1009  1.1      nat 		sc->sc_mux_send_ack = false;
   1010  1.1      nat 
   1011  1.1      nat #ifdef BTH5_DEBUG
   1012  1.1      nat 	if (bth5_debug == 3)
   1013  1.1      nat 		bth5_packet_print(m);
   1014  1.1      nat #endif
   1015  1.1      nat 
   1016  1.1      nat 	sc->sc_txp = m;
   1017  1.1      nat 	bth5_pktintegrity_transmit(sc);
   1018  1.1      nat }
   1019  1.1      nat 
   1020  1.1      nat static void
   1021  1.1      nat bth5_mux_receive(struct bth5_softc *sc, struct mbuf *m)
   1022  1.1      nat {
   1023  1.1      nat 	bth5_hdr_t *hdrp = mtod(m, bth5_hdr_t *);
   1024  1.1      nat 	const u_int rxack = BTH5_FLAGS_ACK(hdrp->flags);
   1025  1.1      nat 
   1026  1.1      nat 	DPRINTFN(2, ("%s: mux receive: flags=0x%x, ident=%d, rxack=%d\n",
   1027  1.1      nat 	    device_xname(sc->sc_dev), hdrp->flags, hdrp->ident, rxack));
   1028  1.1      nat #ifdef BTH5_DEBUG
   1029  1.1      nat 	if (bth5_debug == 3)
   1030  1.1      nat 		bth5_packet_print(m);
   1031  1.1      nat #endif
   1032  1.1      nat 
   1033  1.1      nat 	bth5_signal_rxack(sc, rxack);
   1034  1.1      nat 
   1035  1.1      nat 	microtime(&sc->sc_mux_lastrx);
   1036  1.1      nat 
   1037  1.1      nat 	/* if the Ack Packet received then discard */
   1038  1.1      nat 	if (BTH5_FLAGS_SEQ(hdrp->flags) == 0 &&
   1039  1.1      nat 	    hdrp->ident == BTH5_IDENT_ACKPKT &&
   1040  1.1      nat 	    BTH5_GET_PLEN(hdrp) == 0) {
   1041  1.5      nat 		sc->sc_seq_txseq = BTH5_FLAGS_ACK(hdrp->flags);
   1042  1.5      nat 		bth5_send_ack_command(sc);
   1043  1.5      nat 		bth5_mux_transmit(sc);
   1044  1.1      nat 		m_freem(m);
   1045  1.1      nat 		return;
   1046  1.1      nat 	}
   1047  1.1      nat 
   1048  1.1      nat 	if (hdrp->flags & BTH5_FLAGS_PROTOCOL_REL)
   1049  1.1      nat 		bth5_sequencing_receive(sc, m);
   1050  1.1      nat 	else
   1051  1.1      nat 		bth5_datagramq_receive(sc, m);
   1052  1.1      nat }
   1053  1.1      nat 
   1054  1.1      nat static __inline void
   1055  1.1      nat bth5_send_ack_command(struct bth5_softc *sc)
   1056  1.1      nat {
   1057  1.1      nat 
   1058  1.1      nat 	DPRINTFN(2, ("%s: mux send_ack_command\n", device_xname(sc->sc_dev)));
   1059  1.1      nat 
   1060  1.1      nat 	sc->sc_mux_send_ack = true;
   1061  1.1      nat }
   1062  1.1      nat 
   1063  1.1      nat static __inline struct mbuf *
   1064  1.1      nat bth5_create_ackpkt(void)
   1065  1.1      nat {
   1066  1.1      nat 	struct mbuf *m;
   1067  1.1      nat 	bth5_hdr_t *hdrp;
   1068  1.1      nat 
   1069  1.1      nat 	MGETHDR(m, M_DONTWAIT, MT_DATA);
   1070  1.1      nat 	if (m != NULL) {
   1071  1.1      nat 		m->m_pkthdr.len = m->m_len = sizeof(bth5_hdr_t);
   1072  1.1      nat 		hdrp = mtod(m, bth5_hdr_t *);
   1073  1.1      nat 		/*
   1074  1.1      nat 		 * An Ack Packet has the following fields:
   1075  1.1      nat 		 *	Ack Field:			txack (not set yet)
   1076  1.1      nat 		 *	Seq Field:			0
   1077  1.1      nat 		 *	Protocol Identifier Field:	0
   1078  1.1      nat 		 *	Protocol Type Field:		Any value
   1079  1.1      nat 		 *	Payload Length Field:		0
   1080  1.1      nat 		 */
   1081  1.1      nat 		memset(hdrp, 0, sizeof(bth5_hdr_t));
   1082  1.1      nat 	}
   1083  1.1      nat 	return m;
   1084  1.1      nat }
   1085  1.1      nat 
   1086  1.1      nat static __inline void
   1087  1.1      nat bth5_set_choke(struct bth5_softc *sc, bool choke)
   1088  1.1      nat {
   1089  1.1      nat 
   1090  1.1      nat 	DPRINTFN(2, ("%s: mux set choke=%d\n", device_xname(sc->sc_dev), choke));
   1091  1.1      nat 
   1092  1.1      nat 	sc->sc_mux_choke = choke;
   1093  1.1      nat }
   1094  1.1      nat 
   1095  1.1      nat 
   1096  1.1      nat /*
   1097  1.1      nat  * BTH5 Sequencing Layer functions
   1098  1.1      nat  */
   1099  1.1      nat static void
   1100  1.1      nat bth5_sequencing_receive(struct bth5_softc *sc, struct mbuf *m)
   1101  1.1      nat {
   1102  1.1      nat 	bth5_hdr_t hdr;
   1103  1.5      nat 	uint32_t exp_rxseq, rxack, rxseq;
   1104  1.1      nat 
   1105  1.3      nat 	exp_rxseq = sc->sc_seq_expected_rxseq & BTH5_FLAGS_SEQ_MASK;
   1106  1.1      nat 	m_copydata(m, 0, sizeof(bth5_hdr_t), &hdr);
   1107  1.1      nat 	rxseq = BTH5_FLAGS_SEQ(hdr.flags);
   1108  1.5      nat 	rxack = BTH5_FLAGS_ACK(hdr.flags);
   1109  1.1      nat 
   1110  1.1      nat 	DPRINTFN(1, ("%s: seq receive: rxseq=%d, expected %d\n",
   1111  1.3      nat 	    device_xname(sc->sc_dev), rxseq, exp_rxseq));
   1112  1.1      nat #ifdef BTH5_DEBUG
   1113  1.1      nat 	if (bth5_debug == 2)
   1114  1.1      nat 		bth5_packet_print(m);
   1115  1.1      nat #endif
   1116  1.1      nat 
   1117  1.1      nat 	/*
   1118  1.1      nat 	 * We remove the header of BTH5 and add the 'uint8_t type' of
   1119  1.1      nat 	 * hci_*_hdr_t to the head.
   1120  1.1      nat 	 */
   1121  1.1      nat 	m_adj(m, sizeof(bth5_hdr_t) - sizeof(uint8_t));
   1122  1.1      nat 
   1123  1.3      nat 	if (rxseq != exp_rxseq) {
   1124  1.1      nat 		m_freem(m);
   1125  1.1      nat 
   1126  1.3      nat 		bth5_send_ack_command(sc);
   1127  1.1      nat 		/* send ack packet, if needly */
   1128  1.1      nat 		bth5_mux_transmit(sc);
   1129  1.1      nat 
   1130  1.1      nat 		return;
   1131  1.1      nat 	}
   1132  1.1      nat 
   1133  1.1      nat 	switch (hdr.ident) {
   1134  1.1      nat 	case BTH5_CHANNEL_HCI_CMD:
   1135  1.1      nat 		*(mtod(m, uint8_t *)) = HCI_CMD_PKT;
   1136  1.1      nat 		if (!hci_input_event(sc->sc_unit, m))
   1137  1.1      nat 			sc->sc_stats.err_rx++;
   1138  1.1      nat 
   1139  1.1      nat 		sc->sc_stats.evt_rx++;
   1140  1.1      nat 		break;
   1141  1.1      nat 
   1142  1.1      nat 	case BTH5_CHANNEL_HCI_EVT:
   1143  1.1      nat 		*(mtod(m, uint8_t *)) = HCI_EVENT_PKT;
   1144  1.1      nat 		if (!hci_input_event(sc->sc_unit, m))
   1145  1.1      nat 			sc->sc_stats.err_rx++;
   1146  1.1      nat 
   1147  1.1      nat 		sc->sc_stats.evt_rx++;
   1148  1.1      nat 		break;
   1149  1.1      nat 
   1150  1.1      nat 	case BTH5_CHANNEL_HCI_ACL:
   1151  1.1      nat 		*(mtod(m, uint8_t *)) = HCI_ACL_DATA_PKT;
   1152  1.1      nat 		if (!hci_input_acl(sc->sc_unit, m))
   1153  1.1      nat 			sc->sc_stats.err_rx++;
   1154  1.1      nat 
   1155  1.1      nat 		sc->sc_stats.acl_rx++;
   1156  1.1      nat 		break;
   1157  1.1      nat 
   1158  1.1      nat 	case BTH5_CHANNEL_HCI_SCO:
   1159  1.1      nat 		*(mtod(m, uint8_t *)) = HCI_SCO_DATA_PKT;
   1160  1.1      nat 		if (!hci_input_sco(sc->sc_unit, m))
   1161  1.1      nat 			sc->sc_stats.err_rx++;
   1162  1.1      nat 
   1163  1.1      nat 		sc->sc_stats.sco_rx++;
   1164  1.1      nat 		break;
   1165  1.1      nat 
   1166  1.1      nat 	default:
   1167  1.1      nat 		aprint_error_dev(sc->sc_dev,
   1168  1.1      nat 		    "received reliable packet with not support channel %d\n",
   1169  1.1      nat 		    hdr.ident);
   1170  1.1      nat 		m_freem(m);
   1171  1.1      nat 		break;
   1172  1.1      nat 	}
   1173  1.5      nat 	bth5_send_ack_command(sc);
   1174  1.5      nat 	sc->sc_seq_txseq = rxack;
   1175  1.5      nat 	sc->sc_seq_expected_rxseq = (rxseq + 1) & BTH5_FLAGS_SEQ_MASK;
   1176  1.5      nat 	sc->sc_seq_total_rxpkts++;
   1177  1.1      nat 
   1178  1.5      nat 	if (sc->sc_seq_total_rxpkts % sc->sc_seq_winack == 0)
   1179  1.5      nat 		bth5_mux_transmit(sc);
   1180  1.1      nat }
   1181  1.1      nat 
   1182  1.1      nat static bool
   1183  1.1      nat bth5_tx_reliable_pkt(struct bth5_softc *sc, struct mbuf *m, u_int protocol_id)
   1184  1.1      nat {
   1185  1.1      nat 	bth5_hdr_t *hdrp;
   1186  1.1      nat 	struct mbuf *_m;
   1187  1.1      nat 	struct mbuf *_retrans;
   1188  1.1      nat 	u_int pldlen;
   1189  1.1      nat 	int s;
   1190  1.1      nat 
   1191  1.1      nat 	DPRINTFN(1, ("%s: seq transmit:"
   1192  1.1      nat 	    "protocol_id=%d, winspace=%d, txseq=%d\n", device_xname(sc->sc_dev),
   1193  1.1      nat 	    protocol_id, sc->sc_seq_winspace, sc->sc_seq_txseq));
   1194  1.1      nat 
   1195  1.1      nat 	for (pldlen = 0, _m = m; _m != NULL; _m = _m->m_next) {
   1196  1.1      nat 		if (_m->m_len < 0)
   1197  1.1      nat 			goto out;
   1198  1.1      nat 		pldlen += _m->m_len;
   1199  1.1      nat 	}
   1200  1.1      nat 	if (pldlen > 0xfff)
   1201  1.1      nat 		goto out;
   1202  1.1      nat 	if (protocol_id == BTH5_IDENT_ACKPKT || protocol_id > 15)
   1203  1.1      nat 		goto out;
   1204  1.1      nat 
   1205  1.1      nat 	if (sc->sc_seq_winspace == 0)
   1206  1.1      nat 		goto out;
   1207  1.1      nat 
   1208  1.1      nat 	M_PREPEND(m, sizeof(bth5_hdr_t), M_DONTWAIT);
   1209  1.1      nat 	if (m == NULL) {
   1210  1.1      nat 		aprint_error_dev(sc->sc_dev, "out of memory\n");
   1211  1.1      nat 		return false;
   1212  1.1      nat 	}
   1213  1.1      nat 	KASSERT(m->m_len >= sizeof(bth5_hdr_t));
   1214  1.1      nat 
   1215  1.1      nat 	hdrp = mtod(m, bth5_hdr_t *);
   1216  1.1      nat 	memset(hdrp, 0, sizeof(bth5_hdr_t));
   1217  1.1      nat 	hdrp->flags |= sc->sc_seq_txseq;
   1218  1.1      nat 	hdrp->ident = protocol_id;
   1219  1.1      nat 
   1220  1.1      nat 	callout_schedule(&sc->sc_seq_timer, sc->sc_seq_timeout);
   1221  1.1      nat 
   1222  1.1      nat 	s = splserial();
   1223  1.1      nat 	MBUFQ_ENQUEUE(&sc->sc_seqq, m);
   1224  1.1      nat 	splx(s);
   1225  1.1      nat 	sc->sc_transmit_callback = bth5_reliabletx_callback;
   1226  1.1      nat 
   1227  1.1      nat #ifdef BTH5_DEBUG
   1228  1.1      nat 	if (bth5_debug == 2)
   1229  1.1      nat 		bth5_packet_print(m);
   1230  1.1      nat #endif
   1231  1.1      nat 
   1232  1.1      nat 	sc->sc_seq_winspace--;
   1233  1.6  mlelstv 	_retrans = m_copym(m, 0, M_COPYALL, M_DONTWAIT);
   1234  1.1      nat 	if (_retrans == NULL) {
   1235  1.1      nat 		aprint_error_dev(sc->sc_dev, "out of memory\n");
   1236  1.1      nat 		goto out;
   1237  1.1      nat 	}
   1238  1.1      nat 	MBUFQ_ENQUEUE(&sc->sc_seq_retryq, _retrans);
   1239  1.1      nat 	bth5_mux_transmit(sc);
   1240  1.5      nat 	sc->sc_seq_txseq = (sc->sc_seq_txseq + 1) & BTH5_FLAGS_SEQ_MASK;
   1241  1.1      nat 
   1242  1.1      nat 	return true;
   1243  1.1      nat out:
   1244  1.1      nat 	m_freem(m);
   1245  1.1      nat 	return false;
   1246  1.1      nat }
   1247  1.1      nat 
   1248  1.1      nat static __inline u_int
   1249  1.1      nat bth5_get_txack(struct bth5_softc *sc)
   1250  1.1      nat {
   1251  1.1      nat 
   1252  1.5      nat 	return sc->sc_seq_expected_rxseq;
   1253  1.1      nat }
   1254  1.1      nat 
   1255  1.1      nat static void
   1256  1.1      nat bth5_signal_rxack(struct bth5_softc *sc, uint32_t rxack)
   1257  1.1      nat {
   1258  1.1      nat 	bth5_hdr_t *hdrp;
   1259  1.1      nat 	struct mbuf *m;
   1260  1.1      nat 	uint32_t seqno = (rxack - 1) & BTH5_FLAGS_SEQ_MASK;
   1261  1.1      nat 	int s;
   1262  1.1      nat 
   1263  1.1      nat 	DPRINTFN(1, ("%s: seq signal rxack: rxack=%d\n",
   1264  1.1      nat 	    device_xname(sc->sc_dev), rxack));
   1265  1.1      nat 
   1266  1.1      nat 	s = splserial();
   1267  1.1      nat 	m = MBUFQ_FIRST(&sc->sc_seq_retryq);
   1268  1.1      nat 	while (m != NULL) {
   1269  1.1      nat 		hdrp = mtod(m, bth5_hdr_t *);
   1270  1.1      nat 		if (BTH5_FLAGS_SEQ(hdrp->flags) == seqno) {
   1271  1.1      nat 			struct mbuf *m0;
   1272  1.1      nat 
   1273  1.1      nat 			for (m0 = MBUFQ_FIRST(&sc->sc_seq_retryq);
   1274  1.1      nat 			    m0 != MBUFQ_NEXT(m);
   1275  1.1      nat 			    m0 = MBUFQ_FIRST(&sc->sc_seq_retryq)) {
   1276  1.1      nat 				MBUFQ_DEQUEUE(&sc->sc_seq_retryq, m0);
   1277  1.1      nat 				m_freem(m0);
   1278  1.1      nat 				sc->sc_seq_winspace++;
   1279  1.5      nat 				if (sc->sc_seq_winspace > sc->sc_seq_winsize)
   1280  1.5      nat 					sc->sc_seq_winspace = sc->sc_seq_winsize;
   1281  1.1      nat 			}
   1282  1.1      nat 			break;
   1283  1.1      nat 		}
   1284  1.1      nat 		m = MBUFQ_NEXT(m);
   1285  1.1      nat 	}
   1286  1.1      nat 	splx(s);
   1287  1.1      nat 	sc->sc_seq_retries = 0;
   1288  1.1      nat 
   1289  1.1      nat 	if (sc->sc_seq_winspace == sc->sc_seq_winsize)
   1290  1.1      nat 		callout_stop(&sc->sc_seq_timer);
   1291  1.1      nat 	else
   1292  1.1      nat 		callout_schedule(&sc->sc_seq_timer, sc->sc_seq_timeout);
   1293  1.1      nat }
   1294  1.1      nat 
   1295  1.1      nat static void
   1296  1.1      nat bth5_reliabletx_callback(struct bth5_softc *sc, struct mbuf *m)
   1297  1.1      nat {
   1298  1.1      nat 
   1299  1.1      nat 	m_freem(m);
   1300  1.1      nat }
   1301  1.1      nat 
   1302  1.1      nat static void
   1303  1.1      nat bth5_timer_timeout(void *arg)
   1304  1.1      nat {
   1305  1.1      nat 	struct bth5_softc *sc = arg;
   1306  1.1      nat 	struct mbuf *m, *_m;
   1307  1.1      nat 	int s, i = 0;
   1308  1.1      nat 
   1309  1.1      nat 	DPRINTFN(1, ("%s: seq timeout: retries=%d\n",
   1310  1.1      nat 	    device_xname(sc->sc_dev), sc->sc_seq_retries));
   1311  1.1      nat 
   1312  1.5      nat 	bth5_send_ack_command(sc);
   1313  1.5      nat 	bth5_mux_transmit(sc);
   1314  1.1      nat 	s = splserial();
   1315  1.1      nat 	for (m = MBUFQ_FIRST(&sc->sc_seq_retryq); m != NULL;
   1316  1.1      nat 	    m = MBUFQ_NEXT(m)) {
   1317  1.1      nat 		_m = m_copym(m, 0, M_COPYALL, M_DONTWAIT);
   1318  1.1      nat 		if (_m == NULL) {
   1319  1.1      nat 			aprint_error_dev(sc->sc_dev, "out of memory\n");
   1320  1.1      nat 			return;
   1321  1.1      nat 		}
   1322  1.1      nat 		MBUFQ_ENQUEUE(&sc->sc_seqq, _m);
   1323  1.1      nat 		i++;
   1324  1.1      nat 	}
   1325  1.1      nat 	splx(s);
   1326  1.1      nat 
   1327  1.1      nat 	if (i != 0) {
   1328  1.1      nat 		if (++sc->sc_seq_retries < sc->sc_seq_retry_limit)
   1329  1.1      nat 			callout_schedule(&sc->sc_seq_timer, sc->sc_seq_timeout);
   1330  1.1      nat 		else {
   1331  1.1      nat 			aprint_error_dev(sc->sc_dev,
   1332  1.1      nat 			    "reached the retry limit."
   1333  1.1      nat 			    " restart the link-establishment\n");
   1334  1.1      nat 			bth5_sequencing_reset(sc);
   1335  1.1      nat 			bth5_start_le(sc);
   1336  1.1      nat 			return;
   1337  1.1      nat 		}
   1338  1.1      nat 	}
   1339  1.1      nat 	bth5_mux_transmit(sc);
   1340  1.1      nat }
   1341  1.1      nat 
   1342  1.1      nat static void
   1343  1.1      nat bth5_sequencing_reset(struct bth5_softc *sc)
   1344  1.1      nat {
   1345  1.1      nat 	int s;
   1346  1.1      nat 
   1347  1.1      nat 	s = splserial();
   1348  1.1      nat 	MBUFQ_DRAIN(&sc->sc_seqq);
   1349  1.1      nat 	MBUFQ_DRAIN(&sc->sc_seq_retryq);
   1350  1.1      nat 	splx(s);
   1351  1.1      nat 
   1352  1.1      nat 
   1353  1.1      nat 	sc->sc_seq_txseq = 0;
   1354  1.1      nat 	sc->sc_seq_winspace = sc->sc_seq_winsize;
   1355  1.1      nat 	sc->sc_seq_retries = 0;
   1356  1.1      nat 	callout_stop(&sc->sc_seq_timer);
   1357  1.1      nat 
   1358  1.1      nat 	sc->sc_mux_send_ack = false;
   1359  1.1      nat 
   1360  1.1      nat 	/* XXXX: expected_rxseq should be set by MUX Layer */
   1361  1.1      nat 	sc->sc_seq_expected_rxseq = 0;
   1362  1.5      nat 	sc->sc_seq_total_rxpkts = 0;
   1363  1.1      nat }
   1364  1.1      nat 
   1365  1.1      nat 
   1366  1.1      nat /*
   1367  1.1      nat  * BTH5 Datagram Queue Layer functions
   1368  1.1      nat  */
   1369  1.1      nat static void
   1370  1.1      nat bth5_datagramq_receive(struct bth5_softc *sc, struct mbuf *m)
   1371  1.1      nat {
   1372  1.1      nat 	bth5_hdr_t hdr;
   1373  1.1      nat 
   1374  1.1      nat 	DPRINTFN(1, ("%s: dgq receive\n", device_xname(sc->sc_dev)));
   1375  1.1      nat #ifdef BTH5_DEBUG
   1376  1.1      nat 	if (bth5_debug == 2)
   1377  1.1      nat 		bth5_packet_print(m);
   1378  1.1      nat #endif
   1379  1.1      nat 
   1380  1.1      nat 	m_copydata(m, 0, sizeof(bth5_hdr_t), &hdr);
   1381  1.1      nat 
   1382  1.1      nat 	switch (hdr.ident) {
   1383  1.1      nat 	case BTH5_CHANNEL_LE:
   1384  1.1      nat 		m_adj(m, sizeof(bth5_hdr_t));
   1385  1.1      nat 		bth5_input_le(sc, m);
   1386  1.1      nat 		break;
   1387  1.1      nat 
   1388  1.1      nat 	case BTH5_CHANNEL_HCI_SCO:
   1389  1.1      nat 		/*
   1390  1.1      nat 		 * We remove the header of BTH5 and add the 'uint8_t type' of
   1391  1.1      nat 		 * hci_scodata_hdr_t to the head.
   1392  1.1      nat 		 */
   1393  1.1      nat 		m_adj(m, sizeof(bth5_hdr_t) - sizeof(uint8_t));
   1394  1.1      nat 		*(mtod(m, uint8_t *)) = HCI_SCO_DATA_PKT;
   1395  1.1      nat 		if (!hci_input_sco(sc->sc_unit, m))
   1396  1.1      nat 			sc->sc_stats.err_rx++;
   1397  1.1      nat 
   1398  1.1      nat 		sc->sc_stats.sco_rx++;
   1399  1.1      nat 		break;
   1400  1.1      nat 
   1401  1.1      nat 	default:
   1402  1.1      nat 		aprint_error_dev(sc->sc_dev,
   1403  1.1      nat 		    "received unreliable packet with not support channel %d\n",
   1404  1.1      nat 		    hdr.ident);
   1405  1.1      nat 		m_freem(m);
   1406  1.1      nat 		break;
   1407  1.1      nat 	}
   1408  1.1      nat }
   1409  1.1      nat 
   1410  1.1      nat static bool
   1411  1.1      nat bth5_tx_unreliable_pkt(struct bth5_softc *sc, struct mbuf *m, u_int protocol_id)
   1412  1.1      nat {
   1413  1.1      nat 	bth5_hdr_t *hdrp;
   1414  1.1      nat 	struct mbuf *_m;
   1415  1.1      nat 	u_int pldlen;
   1416  1.1      nat 	int s;
   1417  1.1      nat 
   1418  1.1      nat 	DPRINTFN(1, ("%s: dgq transmit: protocol_id=%d,",
   1419  1.1      nat 	    device_xname(sc->sc_dev), protocol_id));
   1420  1.1      nat 
   1421  1.1      nat 	for (pldlen = 0, _m = m; _m != NULL; _m = m->m_next) {
   1422  1.1      nat 		if (_m->m_len < 0)
   1423  1.1      nat 			goto out;
   1424  1.1      nat 		pldlen += _m->m_len;
   1425  1.1      nat 	}
   1426  1.1      nat 	DPRINTFN(1, (" pldlen=%d\n", pldlen));
   1427  1.1      nat 	if (pldlen > 0xfff)
   1428  1.1      nat 		goto out;
   1429  1.1      nat 	if (protocol_id == BTH5_IDENT_ACKPKT || protocol_id > 15)
   1430  1.1      nat 		goto out;
   1431  1.1      nat 
   1432  1.1      nat 	M_PREPEND(m, sizeof(bth5_hdr_t), M_DONTWAIT);
   1433  1.1      nat 	if (m == NULL) {
   1434  1.1      nat 		aprint_error_dev(sc->sc_dev, "out of memory\n");
   1435  1.1      nat 		return false;
   1436  1.1      nat 	}
   1437  1.1      nat 	KASSERT(m->m_len >= sizeof(bth5_hdr_t));
   1438  1.1      nat 
   1439  1.1      nat 	hdrp = mtod(m, bth5_hdr_t *);
   1440  1.1      nat 	memset(hdrp, 0, sizeof(bth5_hdr_t));
   1441  1.1      nat 	hdrp->ident = protocol_id;
   1442  1.1      nat 
   1443  1.1      nat 	s = splserial();
   1444  1.1      nat 	MBUFQ_ENQUEUE(&sc->sc_dgq, m);
   1445  1.1      nat 	splx(s);
   1446  1.1      nat 	sc->sc_transmit_callback = bth5_unreliabletx_callback;
   1447  1.1      nat 
   1448  1.1      nat #ifdef BTH5_DEBUG
   1449  1.1      nat 	if (bth5_debug == 2)
   1450  1.1      nat 		bth5_packet_print(m);
   1451  1.1      nat #endif
   1452  1.1      nat 
   1453  1.1      nat 	bth5_mux_transmit(sc);
   1454  1.1      nat 
   1455  1.1      nat 	return true;
   1456  1.1      nat out:
   1457  1.1      nat 	m_freem(m);
   1458  1.1      nat 	return false;
   1459  1.1      nat }
   1460  1.1      nat 
   1461  1.1      nat static void
   1462  1.1      nat bth5_unreliabletx_callback(struct bth5_softc *sc, struct mbuf *m)
   1463  1.1      nat {
   1464  1.1      nat 
   1465  1.1      nat 	if (M_GETCTX(m, void *) == NULL)
   1466  1.1      nat 		m_freem(m);
   1467  1.1      nat 	else if (!hci_complete_sco(sc->sc_unit, m))
   1468  1.1      nat 		sc->sc_stats.err_tx++;
   1469  1.1      nat }
   1470  1.1      nat 
   1471  1.1      nat 
   1472  1.1      nat /*
   1473  1.1      nat  * BTUART H5 Link Establishment Protocol functions
   1474  1.1      nat  */
   1475  1.1      nat static const uint8_t sync[] = BTH5_LE_SYNC;
   1476  1.1      nat static const uint8_t syncresp[] = BTH5_LE_SYNCRESP;
   1477  1.1      nat static const uint8_t conf[] = BTH5_LE_CONF;
   1478  1.1      nat static const uint8_t confresp[] = BTH5_LE_CONFRESP;
   1479  1.1      nat 
   1480  1.1      nat static int
   1481  1.1      nat bth5_start_le(struct bth5_softc *sc)
   1482  1.1      nat {
   1483  1.1      nat 
   1484  1.1      nat 	DPRINTF(("%s: start link-establish\n", device_xname(sc->sc_dev)));
   1485  1.1      nat 
   1486  1.1      nat 	bth5_set_choke(sc, true);
   1487  1.1      nat 
   1488  1.1      nat 	if (!sc->sc_le_muzzled) {
   1489  1.1      nat 		struct mbuf *m;
   1490  1.1      nat 
   1491  1.6  mlelstv 		m = m_gethdr(M_DONTWAIT, MT_DATA);
   1492  1.6  mlelstv 		if (m == NULL) {
   1493  1.6  mlelstv 			aprint_error_dev(sc->sc_dev,
   1494  1.6  mlelstv 			    "le-packet transmit out of memory\n");
   1495  1.6  mlelstv 			return ENOMEM;
   1496  1.6  mlelstv 		}
   1497  1.1      nat 		m->m_pkthdr.len = m->m_len = 0;
   1498  1.1      nat 		m_copyback(m, 0, sizeof(sync), sync);
   1499  1.1      nat 		if (!bth5_tx_unreliable_pkt(sc, m, BTH5_CHANNEL_LE)) {
   1500  1.1      nat 			aprint_error_dev(sc->sc_dev,
   1501  1.1      nat 			    "le-packet transmit failed\n");
   1502  1.1      nat 			return EINVAL;
   1503  1.1      nat 		}
   1504  1.1      nat 	}
   1505  1.1      nat 	callout_schedule(&sc->sc_le_timer, BTH5_LE_TSHY_TIMEOUT);
   1506  1.1      nat 
   1507  1.1      nat 	sc->sc_le_state = le_state_shy;
   1508  1.1      nat 	return 0;
   1509  1.1      nat }
   1510  1.1      nat 
   1511  1.1      nat static void
   1512  1.1      nat bth5_terminate_le(struct bth5_softc *sc)
   1513  1.1      nat {
   1514  1.1      nat 	struct mbuf *m;
   1515  1.1      nat 
   1516  1.1      nat 	/* terminate link-establishment */
   1517  1.1      nat 	callout_stop(&sc->sc_le_timer);
   1518  1.1      nat 	bth5_set_choke(sc, true);
   1519  1.1      nat 	MGETHDR(m, M_DONTWAIT, MT_DATA);
   1520  1.1      nat 	if (m == NULL)
   1521  1.1      nat 		aprint_error_dev(sc->sc_dev, "out of memory\n");
   1522  1.1      nat 	else {
   1523  1.1      nat 		/* length of le packets is 4 */
   1524  1.1      nat 		m->m_pkthdr.len = m->m_len = 0;
   1525  1.1      nat 		m_copyback(m, 0, sizeof(sync), sync);
   1526  1.1      nat 		if (!bth5_tx_unreliable_pkt(sc, m, BTH5_CHANNEL_LE))
   1527  1.1      nat 			aprint_error_dev(sc->sc_dev,
   1528  1.1      nat 			    "link-establishment terminations failed\n");
   1529  1.1      nat 	}
   1530  1.1      nat }
   1531  1.1      nat 
   1532  1.1      nat static void
   1533  1.1      nat bth5_input_le(struct bth5_softc *sc, struct mbuf *m)
   1534  1.1      nat {
   1535  1.1      nat 	uint16_t *rcvpkt;
   1536  1.5      nat 	int i, len;
   1537  1.5      nat 	uint8_t config[3];
   1538  1.1      nat 	const uint8_t *rplypkt;
   1539  1.1      nat 	static struct {
   1540  1.1      nat 		const char *type;
   1541  1.1      nat 		const uint8_t *datap;
   1542  1.1      nat 	} pkt[] = {
   1543  1.1      nat 		{ "sync",	sync },
   1544  1.1      nat 		{ "sync-resp",	syncresp },
   1545  1.1      nat 		{ "conf",	conf },
   1546  1.1      nat 		{ "conf-resp",	confresp },
   1547  1.1      nat 
   1548  1.1      nat 		{ NULL, 0 }
   1549  1.1      nat 	};
   1550  1.1      nat 
   1551  1.1      nat 	DPRINTFN(0, ("%s: le input: state %d, muzzled %d\n",
   1552  1.1      nat 	    device_xname(sc->sc_dev), sc->sc_le_state, sc->sc_le_muzzled));
   1553  1.1      nat #ifdef BTH5_DEBUG
   1554  1.1      nat 	if (bth5_debug == 1)
   1555  1.1      nat 		bth5_packet_print(m);
   1556  1.1      nat #endif
   1557  1.1      nat 
   1558  1.1      nat 	rcvpkt = mtod(m, uint16_t *);
   1559  1.1      nat 	i = 0;
   1560  1.1      nat 
   1561  1.1      nat 	/* length of le packets is 2 */
   1562  1.5      nat 	if (m->m_len >= sizeof(uint16_t))
   1563  1.1      nat 		for (i = 0; pkt[i].type != NULL; i++)
   1564  1.1      nat 			if (*(const uint16_t *)pkt[i].datap == *rcvpkt)
   1565  1.1      nat 				break;
   1566  1.1      nat 	if (m->m_len < sizeof(uint16_t) || pkt[i].type == NULL) {
   1567  1.1      nat 		aprint_error_dev(sc->sc_dev, "received unknown packet\n");
   1568  1.1      nat 		m_freem(m);
   1569  1.1      nat 		return;
   1570  1.1      nat 	}
   1571  1.1      nat 
   1572  1.5      nat 	len = m->m_len;
   1573  1.5      nat 
   1574  1.1      nat 	rplypkt = NULL;
   1575  1.1      nat 	switch (sc->sc_le_state) {
   1576  1.1      nat 	case le_state_shy:
   1577  1.1      nat 		if (*rcvpkt == *(const uint16_t *)sync) {
   1578  1.1      nat 			sc->sc_le_muzzled = false;
   1579  1.1      nat 			rplypkt = syncresp;
   1580  1.1      nat 		} else if (*rcvpkt == *(const uint16_t *)syncresp) {
   1581  1.1      nat 			DPRINTF(("%s: state change to curious\n",
   1582  1.1      nat 			    device_xname(sc->sc_dev)));
   1583  1.3      nat 			rplypkt = conf;
   1584  1.1      nat 			callout_schedule(&sc->sc_le_timer,
   1585  1.1      nat 			    BTH5_LE_TCONF_TIMEOUT);
   1586  1.1      nat 			sc->sc_le_state = le_state_curious;
   1587  1.1      nat 		} else
   1588  1.1      nat 			aprint_error_dev(sc->sc_dev,
   1589  1.1      nat 			    "received an unknown packet at shy\n");
   1590  1.1      nat 		break;
   1591  1.1      nat 
   1592  1.1      nat 	case le_state_curious:
   1593  1.1      nat 		if (*rcvpkt == *(const uint16_t *)sync)
   1594  1.1      nat 			rplypkt = syncresp;
   1595  1.5      nat 		else if (*rcvpkt == *(const uint16_t *)syncresp) {
   1596  1.3      nat 			rplypkt = conf;
   1597  1.5      nat 			len = 3;
   1598  1.5      nat 		}
   1599  1.1      nat 		else if (*rcvpkt == *(const uint16_t *)conf)
   1600  1.1      nat 			rplypkt = confresp;
   1601  1.5      nat 		else if (*rcvpkt == *(const uint16_t *)confresp &&
   1602  1.5      nat 				m->m_len == 3) {
   1603  1.1      nat 			DPRINTF(("%s: state change to garrulous:\n",
   1604  1.1      nat 			    device_xname(sc->sc_dev)));
   1605  1.1      nat 
   1606  1.5      nat 			memcpy(config, conf, sizeof(uint16_t));
   1607  1.5      nat 			config[2] = (uint8_t)rcvpkt[1];
   1608  1.5      nat 			sc->sc_seq_winack = config[2] & BTH5_CONFIG_ACK_MASK;
   1609  1.5      nat 			if (config[2] & BTH5_CONFIG_FLOW_MASK)
   1610  1.5      nat 				sc->sc_oof_flow_control = true;
   1611  1.5      nat 			else
   1612  1.5      nat 				sc->sc_oof_flow_control = false;
   1613  1.5      nat 
   1614  1.5      nat 			bth5_sequencing_reset(sc);
   1615  1.1      nat 			bth5_set_choke(sc, false);
   1616  1.1      nat 			callout_stop(&sc->sc_le_timer);
   1617  1.1      nat 			sc->sc_le_state = le_state_garrulous;
   1618  1.1      nat 		} else
   1619  1.1      nat 			aprint_error_dev(sc->sc_dev,
   1620  1.1      nat 			    "received unknown packet at curious\n");
   1621  1.1      nat 		break;
   1622  1.1      nat 
   1623  1.1      nat 	case le_state_garrulous:
   1624  1.1      nat 		if (*rcvpkt == *(const uint16_t *)conf)
   1625  1.1      nat 			rplypkt = confresp;
   1626  1.1      nat 		else if (*rcvpkt == *(const uint16_t *)sync) {
   1627  1.1      nat 			/* XXXXX */
   1628  1.1      nat 			aprint_error_dev(sc->sc_dev,
   1629  1.1      nat 			    "received sync! peer to reset?\n");
   1630  1.1      nat 
   1631  1.1      nat 			bth5_sequencing_reset(sc);
   1632  1.5      nat 			rplypkt = syncresp;
   1633  1.1      nat 			sc->sc_le_state = le_state_shy;
   1634  1.1      nat 		} else
   1635  1.1      nat 			aprint_error_dev(sc->sc_dev,
   1636  1.1      nat 			    "received unknown packet at garrulous\n");
   1637  1.1      nat 		break;
   1638  1.1      nat 	}
   1639  1.1      nat 
   1640  1.1      nat 	m_freem(m);
   1641  1.1      nat 
   1642  1.1      nat 	if (rplypkt != NULL) {
   1643  1.1      nat 		MGETHDR(m, M_DONTWAIT, MT_DATA);
   1644  1.1      nat 		if (m == NULL)
   1645  1.1      nat 			aprint_error_dev(sc->sc_dev, "out of memory\n");
   1646  1.1      nat 		else {
   1647  1.1      nat 			/* length of le packets is 2 */
   1648  1.1      nat 			m->m_pkthdr.len = m->m_len = 0;
   1649  1.5      nat 			if (rplypkt == (const uint8_t *)&config
   1650  1.5      nat 			    || rplypkt == confresp || rplypkt == conf)
   1651  1.1      nat 				m_copyback(m, 0, len, rplypkt);
   1652  1.1      nat 			else
   1653  1.1      nat 				m_copyback(m, 0, 2, rplypkt);
   1654  1.1      nat 			if (!bth5_tx_unreliable_pkt(sc, m, BTH5_CHANNEL_LE))
   1655  1.1      nat 				aprint_error_dev(sc->sc_dev,
   1656  1.1      nat 				    "le-packet transmit failed\n");
   1657  1.1      nat 		}
   1658  1.1      nat 	}
   1659  1.1      nat }
   1660  1.1      nat 
   1661  1.1      nat static void
   1662  1.1      nat bth5_le_timeout(void *arg)
   1663  1.1      nat {
   1664  1.1      nat 	struct bth5_softc *sc = arg;
   1665  1.1      nat 	struct mbuf *m;
   1666  1.1      nat 	int timeout;
   1667  1.1      nat 	const uint8_t *sndpkt = NULL;
   1668  1.1      nat 
   1669  1.1      nat 	DPRINTFN(0, ("%s: le timeout: state %d, muzzled %d\n",
   1670  1.1      nat 	    device_xname(sc->sc_dev), sc->sc_le_state, sc->sc_le_muzzled));
   1671  1.1      nat 
   1672  1.1      nat 	switch (sc->sc_le_state) {
   1673  1.1      nat 	case le_state_shy:
   1674  1.1      nat 		if (!sc->sc_le_muzzled)
   1675  1.1      nat 			sndpkt = sync;
   1676  1.1      nat 		timeout = BTH5_LE_TSHY_TIMEOUT;
   1677  1.1      nat 		break;
   1678  1.1      nat 
   1679  1.1      nat 	case le_state_curious:
   1680  1.1      nat 		sndpkt = conf;
   1681  1.1      nat 		timeout = BTH5_LE_TCONF_TIMEOUT;
   1682  1.1      nat 		break;
   1683  1.1      nat 
   1684  1.1      nat 	default:
   1685  1.1      nat 		aprint_error_dev(sc->sc_dev,
   1686  1.1      nat 		    "timeout happen at unknown state %d\n", sc->sc_le_state);
   1687  1.1      nat 		return;
   1688  1.1      nat 	}
   1689  1.1      nat 
   1690  1.1      nat 	if (sndpkt != NULL) {
   1691  1.1      nat 		MGETHDR(m, M_DONTWAIT, MT_DATA);
   1692  1.1      nat 		if (m == NULL)
   1693  1.1      nat 			aprint_error_dev(sc->sc_dev, "out of memory\n");
   1694  1.1      nat 		else {
   1695  1.1      nat 			/* length of le packets is 4 */
   1696  1.1      nat 			m->m_pkthdr.len = m->m_len = 0;
   1697  1.1      nat 			if (sndpkt == conf || sndpkt == confresp)
   1698  1.1      nat 				m_copyback(m, 0, 3, sndpkt);
   1699  1.1      nat 			else
   1700  1.1      nat 				m_copyback(m, 0, 2, sndpkt);
   1701  1.1      nat 			if (!bth5_tx_unreliable_pkt(sc, m, BTH5_CHANNEL_LE))
   1702  1.1      nat 				aprint_error_dev(sc->sc_dev,
   1703  1.1      nat 				    "le-packet transmit failed\n");
   1704  1.1      nat 		}
   1705  1.1      nat 	}
   1706  1.1      nat 
   1707  1.1      nat 	callout_schedule(&sc->sc_le_timer, timeout);
   1708  1.1      nat }
   1709  1.1      nat 
   1710  1.1      nat 
   1711  1.1      nat /*
   1712  1.1      nat  * BTUART H5 Serial Protocol functions.
   1713  1.1      nat  */
   1714  1.1      nat static int
   1715  1.1      nat bth5_enable(device_t self)
   1716  1.1      nat {
   1717  1.1      nat 	struct bth5_softc *sc = device_private(self);
   1718  1.1      nat 	int s;
   1719  1.1      nat 
   1720  1.1      nat 	if (sc->sc_flags & BTH5_ENABLED)
   1721  1.1      nat 		return 0;
   1722  1.1      nat 
   1723  1.1      nat 	s = spltty();
   1724  1.1      nat 
   1725  1.1      nat 	sc->sc_flags |= BTH5_ENABLED;
   1726  1.1      nat 	sc->sc_flags &= ~BTH5_XMIT;
   1727  1.1      nat 
   1728  1.1      nat 	splx(s);
   1729  1.1      nat 
   1730  1.1      nat 	return 0;
   1731  1.1      nat }
   1732  1.1      nat 
   1733  1.1      nat static void
   1734  1.1      nat bth5_disable(device_t self)
   1735  1.1      nat {
   1736  1.1      nat 	struct bth5_softc *sc = device_private(self);
   1737  1.1      nat 	int s;
   1738  1.1      nat 
   1739  1.1      nat 	if ((sc->sc_flags & BTH5_ENABLED) == 0)
   1740  1.1      nat 		return;
   1741  1.1      nat 
   1742  1.1      nat 	s = spltty();
   1743  1.1      nat 
   1744  1.1      nat 	if (sc->sc_rxp) {
   1745  1.1      nat 		m_freem(sc->sc_rxp);
   1746  1.1      nat 		sc->sc_rxp = NULL;
   1747  1.1      nat 	}
   1748  1.1      nat 
   1749  1.1      nat 	if (sc->sc_txp) {
   1750  1.1      nat 		m_freem(sc->sc_txp);
   1751  1.1      nat 		sc->sc_txp = NULL;
   1752  1.1      nat 	}
   1753  1.1      nat 
   1754  1.1      nat 	MBUFQ_DRAIN(&sc->sc_cmdq);
   1755  1.1      nat 	MBUFQ_DRAIN(&sc->sc_aclq);
   1756  1.1      nat 	MBUFQ_DRAIN(&sc->sc_scoq);
   1757  1.1      nat 
   1758  1.1      nat 	sc->sc_flags &= ~BTH5_ENABLED;
   1759  1.1      nat 	splx(s);
   1760  1.1      nat }
   1761  1.1      nat 
   1762  1.1      nat static void
   1763  1.1      nat bth5_start(struct bth5_softc *sc)
   1764  1.1      nat {
   1765  1.1      nat 	struct mbuf *m;
   1766  1.1      nat 
   1767  1.1      nat 	KASSERT((sc->sc_flags & BTH5_XMIT) == 0);
   1768  1.1      nat 	KASSERT(sc->sc_txp == NULL);
   1769  1.1      nat 
   1770  1.1      nat 	if (MBUFQ_FIRST(&sc->sc_aclq)) {
   1771  1.1      nat 		MBUFQ_DEQUEUE(&sc->sc_aclq, m);
   1772  1.1      nat 		sc->sc_stats.acl_tx++;
   1773  1.1      nat 		sc->sc_flags |= BTH5_XMIT;
   1774  1.1      nat 		bth5_tx_reliable_pkt(sc, m, BTH5_CHANNEL_HCI_ACL);
   1775  1.1      nat 	}
   1776  1.1      nat 
   1777  1.1      nat 	if (MBUFQ_FIRST(&sc->sc_cmdq)) {
   1778  1.1      nat 		MBUFQ_DEQUEUE(&sc->sc_cmdq, m);
   1779  1.1      nat 		sc->sc_stats.cmd_tx++;
   1780  1.1      nat 		sc->sc_flags |= BTH5_XMIT;
   1781  1.1      nat 		bth5_tx_reliable_pkt(sc, m, BTH5_CHANNEL_HCI_CMD);
   1782  1.1      nat 	}
   1783  1.1      nat 
   1784  1.1      nat 	if (MBUFQ_FIRST(&sc->sc_scoq)) {
   1785  1.1      nat 		MBUFQ_DEQUEUE(&sc->sc_scoq, m);
   1786  1.1      nat 		sc->sc_stats.sco_tx++;
   1787  1.1      nat 		/* XXXX: We can transmit with reliable */
   1788  1.1      nat 		sc->sc_flags |= BTH5_XMIT;
   1789  1.1      nat 		bth5_tx_unreliable_pkt(sc, m, BTH5_CHANNEL_HCI_SCO);
   1790  1.1      nat 	}
   1791  1.1      nat 
   1792  1.1      nat 	return;
   1793  1.1      nat }
   1794  1.1      nat 
   1795  1.1      nat static void
   1796  1.1      nat bth5_output_cmd(device_t self, struct mbuf *m)
   1797  1.1      nat {
   1798  1.1      nat 	struct bth5_softc *sc = device_private(self);
   1799  1.1      nat 	int s;
   1800  1.1      nat 
   1801  1.1      nat 	KASSERT(sc->sc_flags & BTH5_ENABLED);
   1802  1.1      nat 
   1803  1.1      nat 	m_adj(m, sizeof(uint8_t));
   1804  1.1      nat 	M_SETCTX(m, NULL);
   1805  1.1      nat 
   1806  1.1      nat 	s = spltty();
   1807  1.1      nat 	MBUFQ_ENQUEUE(&sc->sc_cmdq, m);
   1808  1.1      nat 	if ((sc->sc_flags & BTH5_XMIT) == 0)
   1809  1.1      nat 		bth5_start(sc);
   1810  1.1      nat 
   1811  1.1      nat 	splx(s);
   1812  1.1      nat }
   1813  1.1      nat 
   1814  1.1      nat static void
   1815  1.1      nat bth5_output_acl(device_t self, struct mbuf *m)
   1816  1.1      nat {
   1817  1.1      nat 	struct bth5_softc *sc = device_private(self);
   1818  1.1      nat 	int s;
   1819  1.1      nat 
   1820  1.1      nat 	KASSERT(sc->sc_flags & BTH5_ENABLED);
   1821  1.1      nat 
   1822  1.1      nat 	m_adj(m, sizeof(uint8_t));
   1823  1.1      nat 	M_SETCTX(m, NULL);
   1824  1.1      nat 
   1825  1.1      nat 	s = spltty();
   1826  1.1      nat 	MBUFQ_ENQUEUE(&sc->sc_aclq, m);
   1827  1.1      nat 	if ((sc->sc_flags & BTH5_XMIT) == 0)
   1828  1.1      nat 		bth5_start(sc);
   1829  1.1      nat 
   1830  1.1      nat 	splx(s);
   1831  1.1      nat }
   1832  1.1      nat 
   1833  1.1      nat static void
   1834  1.1      nat bth5_output_sco(device_t self, struct mbuf *m)
   1835  1.1      nat {
   1836  1.1      nat 	struct bth5_softc *sc = device_private(self);
   1837  1.1      nat 	int s;
   1838  1.1      nat 
   1839  1.1      nat 	KASSERT(sc->sc_flags & BTH5_ENABLED);
   1840  1.1      nat 
   1841  1.1      nat 	m_adj(m, sizeof(uint8_t));
   1842  1.1      nat 
   1843  1.1      nat 	s = spltty();
   1844  1.1      nat 	MBUFQ_ENQUEUE(&sc->sc_scoq, m);
   1845  1.1      nat 	if ((sc->sc_flags & BTH5_XMIT) == 0)
   1846  1.1      nat 		bth5_start(sc);
   1847  1.1      nat 
   1848  1.1      nat 	splx(s);
   1849  1.1      nat }
   1850  1.1      nat 
   1851  1.1      nat static void
   1852  1.1      nat bth5_stats(device_t self, struct bt_stats *dest, int flush)
   1853  1.1      nat {
   1854  1.1      nat 	struct bth5_softc *sc = device_private(self);
   1855  1.1      nat 	int s;
   1856  1.1      nat 
   1857  1.1      nat 	s = spltty();
   1858  1.1      nat 	memcpy(dest, &sc->sc_stats, sizeof(struct bt_stats));
   1859  1.1      nat 
   1860  1.1      nat 	if (flush)
   1861  1.1      nat 		memset(&sc->sc_stats, 0, sizeof(struct bt_stats));
   1862  1.1      nat 
   1863  1.1      nat 	splx(s);
   1864  1.1      nat }
   1865  1.1      nat 
   1866  1.1      nat 
   1867  1.1      nat #ifdef BTH5_DEBUG
   1868  1.1      nat static void
   1869  1.1      nat bth5_packet_print(struct mbuf *m)
   1870  1.1      nat {
   1871  1.1      nat 	int i;
   1872  1.1      nat 	uint8_t *p;
   1873  1.1      nat 
   1874  1.1      nat 	for ( ; m != NULL; m = m->m_next) {
   1875  1.1      nat 		p = mtod(m, uint8_t *);
   1876  1.1      nat 		for (i = 0; i < m->m_len; i++) {
   1877  1.1      nat 			if (i % 16 == 0)
   1878  1.1      nat 				printf(" ");
   1879  1.1      nat 			printf(" %02x", *(p + i));
   1880  1.1      nat 			if (i % 16 == 15)
   1881  1.1      nat 				printf("\n");
   1882  1.1      nat 		}
   1883  1.1      nat 		printf("\n");
   1884  1.1      nat 	}
   1885  1.1      nat }
   1886  1.1      nat #endif
   1887