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