bth5.c revision 1.1 1 /* $NetBSD: bth5.c,v 1.1 2017/08/10 13:22:19 nat Exp $ */
2 /*
3 * Copyright (c) 2017 Nathanial Sloss <nathanialsloss (at) 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.1 2017/08/10 13:22:19 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)
68 int bth5_debug = 3;
69 #else
70 #undef DPRINTF
71 #undef DPRINTFN
72
73 #define DPRINTF(x)
74 #define DPRINTFN(n, x)
75 #endif
76
77 struct 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
137 static int bthfive_match(device_t, cfdata_t, void *);
138 static void bthfive_attach(device_t, device_t, void *);
139 static int bthfive_detach(device_t, int);
140
141 /* tty functions */
142 static int bth5open(dev_t, struct tty *);
143 static int bth5close(struct tty *, int);
144 static int bth5ioctl(struct tty *, u_long, void *, int, struct lwp *);
145
146 static int bth5_slip_transmit(struct tty *);
147 static int bth5_slip_receive(int, struct tty *);
148
149 static void bth5_pktintegrity_transmit(struct bth5_softc *);
150 static void bth5_pktintegrity_receive(struct bth5_softc *, struct mbuf *);
151 static void bth5_crc_update(uint16_t *, uint8_t);
152 static uint16_t bth5_crc_reverse(uint16_t);
153
154 static void bth5_mux_transmit(struct bth5_softc *sc);
155 static void bth5_mux_receive(struct bth5_softc *sc, struct mbuf *m);
156 static __inline void bth5_send_ack_command(struct bth5_softc *sc);
157 static __inline struct mbuf *bth5_create_ackpkt(void);
158 static __inline void bth5_set_choke(struct bth5_softc *, bool);
159
160 static void bth5_sequencing_receive(struct bth5_softc *, struct mbuf *);
161 static bool bth5_tx_reliable_pkt(struct bth5_softc *, struct mbuf *, u_int);
162 static __inline u_int bth5_get_txack(struct bth5_softc *);
163 static void bth5_signal_rxack(struct bth5_softc *, uint32_t);
164 static void bth5_reliabletx_callback(struct bth5_softc *, struct mbuf *);
165 static void bth5_timer_timeout(void *);
166 static void bth5_sequencing_reset(struct bth5_softc *);
167
168 static void bth5_datagramq_receive(struct bth5_softc *, struct mbuf *);
169 static bool bth5_tx_unreliable_pkt(struct bth5_softc *, struct mbuf *, u_int);
170 static void bth5_unreliabletx_callback(struct bth5_softc *, struct mbuf *);
171
172 static int bth5_start_le(struct bth5_softc *);
173 static void bth5_terminate_le(struct bth5_softc *);
174 static void bth5_input_le(struct bth5_softc *, struct mbuf *);
175 static void bth5_le_timeout(void *);
176
177 static void bth5_start(struct bth5_softc *);
178
179 /* bluetooth hci functions */
180 static int bth5_enable(device_t);
181 static void bth5_disable(device_t);
182 static void bth5_output_cmd(device_t, struct mbuf *);
183 static void bth5_output_acl(device_t, struct mbuf *);
184 static void bth5_output_sco(device_t, struct mbuf *);
185 static void bth5_stats(device_t, struct bt_stats *, int);
186
187 #ifdef BTH5_DEBUG
188 static 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 */
196 CFATTACH_DECL_NEW(bthfive, sizeof(struct bth5_softc),
197 bthfive_match, bthfive_attach, bthfive_detach, NULL);
198
199 static 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
212 static 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 */
223 void
224 bthfiveattach(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 */
250 static int
251 bthfive_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 */
264 static void
265 bthfive_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
336 err:
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 */
344 static int
345 bthfive_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 */
368 static int
369 bth5open(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 */
432 static int
433 bth5close(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 */
466 static int
467 bth5ioctl(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 */
496 static int
497 bth5_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
629 static int
630 bth5_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) {
753 discarded:
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 */
771 static void
772 bth5_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
811 static void
812 bth5_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) {
871 discarded:
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
883 static 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
890 static void
891 bth5_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
901 static uint16_t
902 bth5_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 */
919 static void
920 bth5_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 bth5_start(sc);
967 if (sc->sc_mux_send_ack == true) {
968 m = bth5_create_ackpkt();
969 if (m != NULL)
970 goto transmit;
971 aprint_error_dev(sc->sc_dev, "out of memory\n");
972 sc->sc_stats.err_tx++;
973 }
974
975 /* Nothing to send */
976 DPRINTFN(2, ("\n"));
977 return;
978
979 transmit:
980 DPRINTFN(2, (", txack=%d, send_ack=%d\n",
981 bth5_get_txack(sc), sc->sc_mux_send_ack));
982
983 hdrp = mtod(m, bth5_hdr_t *);
984 hdrp->flags |=
985 (bth5_get_txack(sc) << BTH5_FLAGS_ACK_SHIFT) & BTH5_FLAGS_ACK_MASK;
986 if (sc->sc_mux_send_ack == true)
987 sc->sc_mux_send_ack = false;
988
989 #ifdef BTH5_DEBUG
990 if (bth5_debug == 3)
991 bth5_packet_print(m);
992 #endif
993
994 sc->sc_txp = m;
995 bth5_pktintegrity_transmit(sc);
996 }
997
998 static void
999 bth5_mux_receive(struct bth5_softc *sc, struct mbuf *m)
1000 {
1001 bth5_hdr_t *hdrp = mtod(m, bth5_hdr_t *);
1002 const u_int rxack = BTH5_FLAGS_ACK(hdrp->flags);
1003
1004 DPRINTFN(2, ("%s: mux receive: flags=0x%x, ident=%d, rxack=%d\n",
1005 device_xname(sc->sc_dev), hdrp->flags, hdrp->ident, rxack));
1006 #ifdef BTH5_DEBUG
1007 if (bth5_debug == 3)
1008 bth5_packet_print(m);
1009 #endif
1010
1011 bth5_signal_rxack(sc, rxack);
1012
1013 microtime(&sc->sc_mux_lastrx);
1014
1015 /* if the Ack Packet received then discard */
1016 if (BTH5_FLAGS_SEQ(hdrp->flags) == 0 &&
1017 hdrp->ident == BTH5_IDENT_ACKPKT &&
1018 BTH5_GET_PLEN(hdrp) == 0) {
1019 m_freem(m);
1020 return;
1021 }
1022
1023 if (hdrp->flags & BTH5_FLAGS_PROTOCOL_REL)
1024 bth5_sequencing_receive(sc, m);
1025 else
1026 bth5_datagramq_receive(sc, m);
1027 }
1028
1029 static __inline void
1030 bth5_send_ack_command(struct bth5_softc *sc)
1031 {
1032
1033 DPRINTFN(2, ("%s: mux send_ack_command\n", device_xname(sc->sc_dev)));
1034
1035 sc->sc_mux_send_ack = true;
1036 }
1037
1038 static __inline struct mbuf *
1039 bth5_create_ackpkt(void)
1040 {
1041 struct mbuf *m;
1042 bth5_hdr_t *hdrp;
1043
1044 MGETHDR(m, M_DONTWAIT, MT_DATA);
1045 if (m != NULL) {
1046 m->m_pkthdr.len = m->m_len = sizeof(bth5_hdr_t);
1047 hdrp = mtod(m, bth5_hdr_t *);
1048 /*
1049 * An Ack Packet has the following fields:
1050 * Ack Field: txack (not set yet)
1051 * Seq Field: 0
1052 * Protocol Identifier Field: 0
1053 * Protocol Type Field: Any value
1054 * Payload Length Field: 0
1055 */
1056 memset(hdrp, 0, sizeof(bth5_hdr_t));
1057 }
1058 return m;
1059 }
1060
1061 static __inline void
1062 bth5_set_choke(struct bth5_softc *sc, bool choke)
1063 {
1064
1065 DPRINTFN(2, ("%s: mux set choke=%d\n", device_xname(sc->sc_dev), choke));
1066
1067 sc->sc_mux_choke = choke;
1068 }
1069
1070
1071 /*
1072 * BTH5 Sequencing Layer functions
1073 */
1074 static void
1075 bth5_sequencing_receive(struct bth5_softc *sc, struct mbuf *m)
1076 {
1077 bth5_hdr_t hdr;
1078 uint32_t rxseq;
1079
1080 m_copydata(m, 0, sizeof(bth5_hdr_t), &hdr);
1081 rxseq = BTH5_FLAGS_SEQ(hdr.flags);
1082
1083 DPRINTFN(1, ("%s: seq receive: rxseq=%d, expected %d\n",
1084 device_xname(sc->sc_dev), rxseq, sc->sc_seq_expected_rxseq));
1085 #ifdef BTH5_DEBUG
1086 if (bth5_debug == 2)
1087 bth5_packet_print(m);
1088 #endif
1089
1090 /*
1091 * We remove the header of BTH5 and add the 'uint8_t type' of
1092 * hci_*_hdr_t to the head.
1093 */
1094 m_adj(m, sizeof(bth5_hdr_t) - sizeof(uint8_t));
1095
1096 if (rxseq != sc->sc_seq_expected_rxseq) {
1097 m_freem(m);
1098
1099 /* send ack packet, if needly */
1100 bth5_mux_transmit(sc);
1101
1102 return;
1103 }
1104
1105 switch (hdr.ident) {
1106 case BTH5_CHANNEL_HCI_CMD:
1107 *(mtod(m, uint8_t *)) = HCI_CMD_PKT;
1108 if (!hci_input_event(sc->sc_unit, m))
1109 sc->sc_stats.err_rx++;
1110
1111 sc->sc_stats.evt_rx++;
1112 break;
1113
1114 case BTH5_CHANNEL_HCI_EVT:
1115 *(mtod(m, uint8_t *)) = HCI_EVENT_PKT;
1116 if (!hci_input_event(sc->sc_unit, m))
1117 sc->sc_stats.err_rx++;
1118
1119 sc->sc_stats.evt_rx++;
1120 break;
1121
1122 case BTH5_CHANNEL_HCI_ACL:
1123 *(mtod(m, uint8_t *)) = HCI_ACL_DATA_PKT;
1124 if (!hci_input_acl(sc->sc_unit, m))
1125 sc->sc_stats.err_rx++;
1126
1127 sc->sc_stats.acl_rx++;
1128 break;
1129
1130 case BTH5_CHANNEL_HCI_SCO:
1131 *(mtod(m, uint8_t *)) = HCI_SCO_DATA_PKT;
1132 if (!hci_input_sco(sc->sc_unit, m))
1133 sc->sc_stats.err_rx++;
1134
1135 sc->sc_stats.sco_rx++;
1136 break;
1137
1138 default:
1139 aprint_error_dev(sc->sc_dev,
1140 "received reliable packet with not support channel %d\n",
1141 hdr.ident);
1142 m_freem(m);
1143 break;
1144 }
1145
1146 sc->sc_seq_expected_rxseq =
1147 (sc->sc_seq_expected_rxseq + 1) & BTH5_FLAGS_SEQ_MASK;
1148 sc->sc_seq_txack = sc->sc_seq_expected_rxseq;
1149 bth5_send_ack_command(sc);
1150 }
1151
1152 static bool
1153 bth5_tx_reliable_pkt(struct bth5_softc *sc, struct mbuf *m, u_int protocol_id)
1154 {
1155 bth5_hdr_t *hdrp;
1156 struct mbuf *_m;
1157 struct mbuf *_retrans;
1158 u_int pldlen;
1159 int s;
1160
1161 DPRINTFN(1, ("%s: seq transmit:"
1162 "protocol_id=%d, winspace=%d, txseq=%d\n", device_xname(sc->sc_dev),
1163 protocol_id, sc->sc_seq_winspace, sc->sc_seq_txseq));
1164
1165 for (pldlen = 0, _m = m; _m != NULL; _m = _m->m_next) {
1166 if (_m->m_len < 0)
1167 goto out;
1168 pldlen += _m->m_len;
1169 }
1170 if (pldlen > 0xfff)
1171 goto out;
1172 if (protocol_id == BTH5_IDENT_ACKPKT || protocol_id > 15)
1173 goto out;
1174
1175 if (sc->sc_seq_winspace == 0)
1176 goto out;
1177
1178 M_PREPEND(m, sizeof(bth5_hdr_t), M_DONTWAIT);
1179 if (m == NULL) {
1180 aprint_error_dev(sc->sc_dev, "out of memory\n");
1181 return false;
1182 }
1183 KASSERT(m->m_len >= sizeof(bth5_hdr_t));
1184
1185 hdrp = mtod(m, bth5_hdr_t *);
1186 memset(hdrp, 0, sizeof(bth5_hdr_t));
1187 hdrp->flags |= sc->sc_seq_txseq;
1188 hdrp->ident = protocol_id;
1189
1190 callout_schedule(&sc->sc_seq_timer, sc->sc_seq_timeout);
1191
1192 s = splserial();
1193 MBUFQ_ENQUEUE(&sc->sc_seqq, m);
1194 splx(s);
1195 sc->sc_transmit_callback = bth5_reliabletx_callback;
1196
1197 #ifdef BTH5_DEBUG
1198 if (bth5_debug == 2)
1199 bth5_packet_print(m);
1200 #endif
1201
1202 sc->sc_seq_txseq = (sc->sc_seq_txseq + 1) & BTH5_FLAGS_SEQ_MASK;
1203 sc->sc_seq_winspace--;
1204 _retrans = m_copym(m, 0, M_COPYALL, M_WAIT);
1205 if (_retrans == NULL) {
1206 aprint_error_dev(sc->sc_dev, "out of memory\n");
1207 goto out;
1208 }
1209 MBUFQ_ENQUEUE(&sc->sc_seq_retryq, _retrans);
1210 bth5_mux_transmit(sc);
1211
1212 return true;
1213 out:
1214 m_freem(m);
1215 return false;
1216 }
1217
1218 static __inline u_int
1219 bth5_get_txack(struct bth5_softc *sc)
1220 {
1221
1222 return sc->sc_seq_txack;
1223 }
1224
1225 static void
1226 bth5_signal_rxack(struct bth5_softc *sc, uint32_t rxack)
1227 {
1228 bth5_hdr_t *hdrp;
1229 struct mbuf *m;
1230 uint32_t seqno = (rxack - 1) & BTH5_FLAGS_SEQ_MASK;
1231 int s;
1232
1233 DPRINTFN(1, ("%s: seq signal rxack: rxack=%d\n",
1234 device_xname(sc->sc_dev), rxack));
1235
1236 s = splserial();
1237 m = MBUFQ_FIRST(&sc->sc_seq_retryq);
1238 while (m != NULL) {
1239 hdrp = mtod(m, bth5_hdr_t *);
1240 if (BTH5_FLAGS_SEQ(hdrp->flags) == seqno) {
1241 struct mbuf *m0;
1242
1243 for (m0 = MBUFQ_FIRST(&sc->sc_seq_retryq);
1244 m0 != MBUFQ_NEXT(m);
1245 m0 = MBUFQ_FIRST(&sc->sc_seq_retryq)) {
1246 MBUFQ_DEQUEUE(&sc->sc_seq_retryq, m0);
1247 m_freem(m0);
1248 sc->sc_seq_winspace++;
1249 }
1250 break;
1251 }
1252 m = MBUFQ_NEXT(m);
1253 }
1254 splx(s);
1255 sc->sc_seq_retries = 0;
1256
1257 if (sc->sc_seq_winspace == sc->sc_seq_winsize)
1258 callout_stop(&sc->sc_seq_timer);
1259 else
1260 callout_schedule(&sc->sc_seq_timer, sc->sc_seq_timeout);
1261 }
1262
1263 static void
1264 bth5_reliabletx_callback(struct bth5_softc *sc, struct mbuf *m)
1265 {
1266
1267 m_freem(m);
1268 }
1269
1270 static void
1271 bth5_timer_timeout(void *arg)
1272 {
1273 struct bth5_softc *sc = arg;
1274 struct mbuf *m, *_m;
1275 int s, i = 0;
1276
1277 DPRINTFN(1, ("%s: seq timeout: retries=%d\n",
1278 device_xname(sc->sc_dev), sc->sc_seq_retries));
1279
1280 s = splserial();
1281 for (m = MBUFQ_FIRST(&sc->sc_seq_retryq); m != NULL;
1282 m = MBUFQ_NEXT(m)) {
1283 _m = m_copym(m, 0, M_COPYALL, M_DONTWAIT);
1284 if (_m == NULL) {
1285 aprint_error_dev(sc->sc_dev, "out of memory\n");
1286 return;
1287 }
1288 MBUFQ_ENQUEUE(&sc->sc_seqq, _m);
1289 i++;
1290 }
1291 splx(s);
1292
1293 if (i != 0) {
1294 if (++sc->sc_seq_retries < sc->sc_seq_retry_limit)
1295 callout_schedule(&sc->sc_seq_timer, sc->sc_seq_timeout);
1296 else {
1297 aprint_error_dev(sc->sc_dev,
1298 "reached the retry limit."
1299 " restart the link-establishment\n");
1300 bth5_sequencing_reset(sc);
1301 bth5_start_le(sc);
1302 return;
1303 }
1304 }
1305 bth5_mux_transmit(sc);
1306 }
1307
1308 static void
1309 bth5_sequencing_reset(struct bth5_softc *sc)
1310 {
1311 int s;
1312
1313 s = splserial();
1314 MBUFQ_DRAIN(&sc->sc_seqq);
1315 MBUFQ_DRAIN(&sc->sc_seq_retryq);
1316 splx(s);
1317
1318
1319 sc->sc_seq_txseq = 0;
1320 sc->sc_seq_txack = 0;
1321 sc->sc_seq_winspace = sc->sc_seq_winsize;
1322 sc->sc_seq_retries = 0;
1323 callout_stop(&sc->sc_seq_timer);
1324
1325 sc->sc_mux_send_ack = false;
1326
1327 /* XXXX: expected_rxseq should be set by MUX Layer */
1328 sc->sc_seq_expected_rxseq = 0;
1329 }
1330
1331
1332 /*
1333 * BTH5 Datagram Queue Layer functions
1334 */
1335 static void
1336 bth5_datagramq_receive(struct bth5_softc *sc, struct mbuf *m)
1337 {
1338 bth5_hdr_t hdr;
1339
1340 DPRINTFN(1, ("%s: dgq receive\n", device_xname(sc->sc_dev)));
1341 #ifdef BTH5_DEBUG
1342 if (bth5_debug == 2)
1343 bth5_packet_print(m);
1344 #endif
1345
1346 m_copydata(m, 0, sizeof(bth5_hdr_t), &hdr);
1347
1348 switch (hdr.ident) {
1349 case BTH5_CHANNEL_LE:
1350 m_adj(m, sizeof(bth5_hdr_t));
1351 bth5_input_le(sc, m);
1352 break;
1353
1354 case BTH5_CHANNEL_HCI_SCO:
1355 /*
1356 * We remove the header of BTH5 and add the 'uint8_t type' of
1357 * hci_scodata_hdr_t to the head.
1358 */
1359 m_adj(m, sizeof(bth5_hdr_t) - sizeof(uint8_t));
1360 *(mtod(m, uint8_t *)) = HCI_SCO_DATA_PKT;
1361 if (!hci_input_sco(sc->sc_unit, m))
1362 sc->sc_stats.err_rx++;
1363
1364 sc->sc_stats.sco_rx++;
1365 break;
1366
1367 default:
1368 aprint_error_dev(sc->sc_dev,
1369 "received unreliable packet with not support channel %d\n",
1370 hdr.ident);
1371 m_freem(m);
1372 break;
1373 }
1374 }
1375
1376 static bool
1377 bth5_tx_unreliable_pkt(struct bth5_softc *sc, struct mbuf *m, u_int protocol_id)
1378 {
1379 bth5_hdr_t *hdrp;
1380 struct mbuf *_m;
1381 u_int pldlen;
1382 int s;
1383
1384 DPRINTFN(1, ("%s: dgq transmit: protocol_id=%d,",
1385 device_xname(sc->sc_dev), protocol_id));
1386
1387 for (pldlen = 0, _m = m; _m != NULL; _m = m->m_next) {
1388 if (_m->m_len < 0)
1389 goto out;
1390 pldlen += _m->m_len;
1391 }
1392 DPRINTFN(1, (" pldlen=%d\n", pldlen));
1393 if (pldlen > 0xfff)
1394 goto out;
1395 if (protocol_id == BTH5_IDENT_ACKPKT || protocol_id > 15)
1396 goto out;
1397
1398 M_PREPEND(m, sizeof(bth5_hdr_t), M_DONTWAIT);
1399 if (m == NULL) {
1400 aprint_error_dev(sc->sc_dev, "out of memory\n");
1401 return false;
1402 }
1403 KASSERT(m->m_len >= sizeof(bth5_hdr_t));
1404
1405 hdrp = mtod(m, bth5_hdr_t *);
1406 memset(hdrp, 0, sizeof(bth5_hdr_t));
1407 hdrp->ident = protocol_id;
1408
1409 s = splserial();
1410 MBUFQ_ENQUEUE(&sc->sc_dgq, m);
1411 splx(s);
1412 sc->sc_transmit_callback = bth5_unreliabletx_callback;
1413
1414 #ifdef BTH5_DEBUG
1415 if (bth5_debug == 2)
1416 bth5_packet_print(m);
1417 #endif
1418
1419 bth5_mux_transmit(sc);
1420
1421 return true;
1422 out:
1423 m_freem(m);
1424 return false;
1425 }
1426
1427 static void
1428 bth5_unreliabletx_callback(struct bth5_softc *sc, struct mbuf *m)
1429 {
1430
1431 if (M_GETCTX(m, void *) == NULL)
1432 m_freem(m);
1433 else if (!hci_complete_sco(sc->sc_unit, m))
1434 sc->sc_stats.err_tx++;
1435 }
1436
1437
1438 /*
1439 * BTUART H5 Link Establishment Protocol functions
1440 */
1441 static const uint8_t sync[] = BTH5_LE_SYNC;
1442 static const uint8_t syncresp[] = BTH5_LE_SYNCRESP;
1443 static const uint8_t conf[] = BTH5_LE_CONF;
1444 static const uint8_t confresp[] = BTH5_LE_CONFRESP;
1445
1446 static int
1447 bth5_start_le(struct bth5_softc *sc)
1448 {
1449
1450 DPRINTF(("%s: start link-establish\n", device_xname(sc->sc_dev)));
1451
1452 bth5_set_choke(sc, true);
1453
1454 if (!sc->sc_le_muzzled) {
1455 struct mbuf *m;
1456
1457 m = m_gethdr(M_WAIT, MT_DATA);
1458 m->m_pkthdr.len = m->m_len = 0;
1459 m_copyback(m, 0, sizeof(sync), sync);
1460 if (!bth5_tx_unreliable_pkt(sc, m, BTH5_CHANNEL_LE)) {
1461 aprint_error_dev(sc->sc_dev,
1462 "le-packet transmit failed\n");
1463 return EINVAL;
1464 }
1465 }
1466 callout_schedule(&sc->sc_le_timer, BTH5_LE_TSHY_TIMEOUT);
1467
1468 sc->sc_le_state = le_state_shy;
1469 return 0;
1470 }
1471
1472 static void
1473 bth5_terminate_le(struct bth5_softc *sc)
1474 {
1475 struct mbuf *m;
1476
1477 /* terminate link-establishment */
1478 callout_stop(&sc->sc_le_timer);
1479 bth5_set_choke(sc, true);
1480 MGETHDR(m, M_DONTWAIT, MT_DATA);
1481 if (m == NULL)
1482 aprint_error_dev(sc->sc_dev, "out of memory\n");
1483 else {
1484 /* length of le packets is 4 */
1485 m->m_pkthdr.len = m->m_len = 0;
1486 m_copyback(m, 0, sizeof(sync), sync);
1487 if (!bth5_tx_unreliable_pkt(sc, m, BTH5_CHANNEL_LE))
1488 aprint_error_dev(sc->sc_dev,
1489 "link-establishment terminations failed\n");
1490 }
1491 }
1492
1493 static void
1494 bth5_input_le(struct bth5_softc *sc, struct mbuf *m)
1495 {
1496 uint16_t *rcvpkt;
1497 int i;
1498 const uint8_t *rplypkt;
1499 static struct {
1500 const char *type;
1501 const uint8_t *datap;
1502 } pkt[] = {
1503 { "sync", sync },
1504 { "sync-resp", syncresp },
1505 { "conf", conf },
1506 { "conf-resp", confresp },
1507
1508 { NULL, 0 }
1509 };
1510
1511 DPRINTFN(0, ("%s: le input: state %d, muzzled %d\n",
1512 device_xname(sc->sc_dev), sc->sc_le_state, sc->sc_le_muzzled));
1513 #ifdef BTH5_DEBUG
1514 if (bth5_debug == 1)
1515 bth5_packet_print(m);
1516 #endif
1517
1518 rcvpkt = mtod(m, uint16_t *);
1519 i = 0;
1520
1521 /* length of le packets is 2 */
1522 if (m->m_len == sizeof(uint16_t))
1523 for (i = 0; pkt[i].type != NULL; i++)
1524 if (*(const uint16_t *)pkt[i].datap == *rcvpkt)
1525 break;
1526 if (m->m_len < sizeof(uint16_t) || pkt[i].type == NULL) {
1527 aprint_error_dev(sc->sc_dev, "received unknown packet\n");
1528 m_freem(m);
1529 return;
1530 }
1531
1532 rplypkt = NULL;
1533 switch (sc->sc_le_state) {
1534 case le_state_shy:
1535 if (*rcvpkt == *(const uint16_t *)sync) {
1536 sc->sc_le_muzzled = false;
1537 rplypkt = syncresp;
1538 } else if (*rcvpkt == *(const uint16_t *)syncresp) {
1539 DPRINTF(("%s: state change to curious\n",
1540 device_xname(sc->sc_dev)));
1541
1542 callout_schedule(&sc->sc_le_timer,
1543 BTH5_LE_TCONF_TIMEOUT);
1544 sc->sc_le_state = le_state_curious;
1545 } else
1546 aprint_error_dev(sc->sc_dev,
1547 "received an unknown packet at shy\n");
1548 break;
1549
1550 case le_state_curious:
1551 if (*rcvpkt == *(const uint16_t *)sync)
1552 rplypkt = syncresp;
1553 else if (*rcvpkt == *(const uint16_t *)conf)
1554 rplypkt = confresp;
1555 else if (*rcvpkt == *(const uint16_t *)confresp) {
1556 DPRINTF(("%s: state change to garrulous:\n",
1557 device_xname(sc->sc_dev)));
1558
1559 bth5_set_choke(sc, false);
1560 callout_stop(&sc->sc_le_timer);
1561 sc->sc_le_state = le_state_garrulous;
1562 } else
1563 aprint_error_dev(sc->sc_dev,
1564 "received unknown packet at curious\n");
1565 break;
1566
1567 case le_state_garrulous:
1568 if (*rcvpkt == *(const uint16_t *)conf)
1569 rplypkt = confresp;
1570 else if (*rcvpkt == *(const uint16_t *)sync) {
1571 /* XXXXX */
1572 aprint_error_dev(sc->sc_dev,
1573 "received sync! peer to reset?\n");
1574
1575 bth5_sequencing_reset(sc);
1576 rplypkt = sync;
1577 sc->sc_le_state = le_state_shy;
1578 } else
1579 aprint_error_dev(sc->sc_dev,
1580 "received unknown packet at garrulous\n");
1581 break;
1582 }
1583
1584 int len = m->m_len;
1585 m_freem(m);
1586
1587 if (rplypkt != NULL) {
1588 MGETHDR(m, M_DONTWAIT, MT_DATA);
1589 if (m == NULL)
1590 aprint_error_dev(sc->sc_dev, "out of memory\n");
1591 else {
1592 /* length of le packets is 2 */
1593 m->m_pkthdr.len = m->m_len = 0;
1594 if (rplypkt == confresp || rplypkt == conf)
1595 m_copyback(m, 0, len, rplypkt);
1596 else
1597 m_copyback(m, 0, 2, rplypkt);
1598 if (!bth5_tx_unreliable_pkt(sc, m, BTH5_CHANNEL_LE))
1599 aprint_error_dev(sc->sc_dev,
1600 "le-packet transmit failed\n");
1601 }
1602 }
1603 }
1604
1605 static void
1606 bth5_le_timeout(void *arg)
1607 {
1608 struct bth5_softc *sc = arg;
1609 struct mbuf *m;
1610 int timeout;
1611 const uint8_t *sndpkt = NULL;
1612
1613 DPRINTFN(0, ("%s: le timeout: state %d, muzzled %d\n",
1614 device_xname(sc->sc_dev), sc->sc_le_state, sc->sc_le_muzzled));
1615
1616 switch (sc->sc_le_state) {
1617 case le_state_shy:
1618 if (!sc->sc_le_muzzled)
1619 sndpkt = sync;
1620 timeout = BTH5_LE_TSHY_TIMEOUT;
1621 break;
1622
1623 case le_state_curious:
1624 sndpkt = conf;
1625 timeout = BTH5_LE_TCONF_TIMEOUT;
1626 break;
1627
1628 default:
1629 aprint_error_dev(sc->sc_dev,
1630 "timeout happen at unknown state %d\n", sc->sc_le_state);
1631 return;
1632 }
1633
1634 if (sndpkt != NULL) {
1635 MGETHDR(m, M_DONTWAIT, MT_DATA);
1636 if (m == NULL)
1637 aprint_error_dev(sc->sc_dev, "out of memory\n");
1638 else {
1639 /* length of le packets is 4 */
1640 m->m_pkthdr.len = m->m_len = 0;
1641 if (sndpkt == conf || sndpkt == confresp)
1642 m_copyback(m, 0, 3, sndpkt);
1643 else
1644 m_copyback(m, 0, 2, sndpkt);
1645 if (!bth5_tx_unreliable_pkt(sc, m, BTH5_CHANNEL_LE))
1646 aprint_error_dev(sc->sc_dev,
1647 "le-packet transmit failed\n");
1648 }
1649 }
1650
1651 callout_schedule(&sc->sc_le_timer, timeout);
1652 }
1653
1654
1655 /*
1656 * BTUART H5 Serial Protocol functions.
1657 */
1658 static int
1659 bth5_enable(device_t self)
1660 {
1661 struct bth5_softc *sc = device_private(self);
1662 int s;
1663
1664 if (sc->sc_flags & BTH5_ENABLED)
1665 return 0;
1666
1667 s = spltty();
1668
1669 sc->sc_flags |= BTH5_ENABLED;
1670 sc->sc_flags &= ~BTH5_XMIT;
1671
1672 splx(s);
1673
1674 return 0;
1675 }
1676
1677 static void
1678 bth5_disable(device_t self)
1679 {
1680 struct bth5_softc *sc = device_private(self);
1681 int s;
1682
1683 if ((sc->sc_flags & BTH5_ENABLED) == 0)
1684 return;
1685
1686 s = spltty();
1687
1688 if (sc->sc_rxp) {
1689 m_freem(sc->sc_rxp);
1690 sc->sc_rxp = NULL;
1691 }
1692
1693 if (sc->sc_txp) {
1694 m_freem(sc->sc_txp);
1695 sc->sc_txp = NULL;
1696 }
1697
1698 MBUFQ_DRAIN(&sc->sc_cmdq);
1699 MBUFQ_DRAIN(&sc->sc_aclq);
1700 MBUFQ_DRAIN(&sc->sc_scoq);
1701
1702 sc->sc_flags &= ~BTH5_ENABLED;
1703 splx(s);
1704 }
1705
1706 static void
1707 bth5_start(struct bth5_softc *sc)
1708 {
1709 struct mbuf *m;
1710
1711 KASSERT((sc->sc_flags & BTH5_XMIT) == 0);
1712 KASSERT(sc->sc_txp == NULL);
1713
1714 if (MBUFQ_FIRST(&sc->sc_aclq)) {
1715 MBUFQ_DEQUEUE(&sc->sc_aclq, m);
1716 sc->sc_stats.acl_tx++;
1717 sc->sc_flags |= BTH5_XMIT;
1718 bth5_tx_reliable_pkt(sc, m, BTH5_CHANNEL_HCI_ACL);
1719 }
1720
1721 if (MBUFQ_FIRST(&sc->sc_cmdq)) {
1722 MBUFQ_DEQUEUE(&sc->sc_cmdq, m);
1723 sc->sc_stats.cmd_tx++;
1724 sc->sc_flags |= BTH5_XMIT;
1725 bth5_tx_reliable_pkt(sc, m, BTH5_CHANNEL_HCI_CMD);
1726 }
1727
1728 if (MBUFQ_FIRST(&sc->sc_scoq)) {
1729 MBUFQ_DEQUEUE(&sc->sc_scoq, m);
1730 sc->sc_stats.sco_tx++;
1731 /* XXXX: We can transmit with reliable */
1732 sc->sc_flags |= BTH5_XMIT;
1733 bth5_tx_unreliable_pkt(sc, m, BTH5_CHANNEL_HCI_SCO);
1734 }
1735
1736 return;
1737 }
1738
1739 static void
1740 bth5_output_cmd(device_t self, struct mbuf *m)
1741 {
1742 struct bth5_softc *sc = device_private(self);
1743 int s;
1744
1745 KASSERT(sc->sc_flags & BTH5_ENABLED);
1746
1747 m_adj(m, sizeof(uint8_t));
1748 M_SETCTX(m, NULL);
1749
1750 s = spltty();
1751 MBUFQ_ENQUEUE(&sc->sc_cmdq, m);
1752 if ((sc->sc_flags & BTH5_XMIT) == 0)
1753 bth5_start(sc);
1754
1755 splx(s);
1756 }
1757
1758 static void
1759 bth5_output_acl(device_t self, struct mbuf *m)
1760 {
1761 struct bth5_softc *sc = device_private(self);
1762 int s;
1763
1764 KASSERT(sc->sc_flags & BTH5_ENABLED);
1765
1766 m_adj(m, sizeof(uint8_t));
1767 M_SETCTX(m, NULL);
1768
1769 s = spltty();
1770 MBUFQ_ENQUEUE(&sc->sc_aclq, m);
1771 if ((sc->sc_flags & BTH5_XMIT) == 0)
1772 bth5_start(sc);
1773
1774 splx(s);
1775 }
1776
1777 static void
1778 bth5_output_sco(device_t self, struct mbuf *m)
1779 {
1780 struct bth5_softc *sc = device_private(self);
1781 int s;
1782
1783 KASSERT(sc->sc_flags & BTH5_ENABLED);
1784
1785 m_adj(m, sizeof(uint8_t));
1786
1787 s = spltty();
1788 MBUFQ_ENQUEUE(&sc->sc_scoq, m);
1789 if ((sc->sc_flags & BTH5_XMIT) == 0)
1790 bth5_start(sc);
1791
1792 splx(s);
1793 }
1794
1795 static void
1796 bth5_stats(device_t self, struct bt_stats *dest, int flush)
1797 {
1798 struct bth5_softc *sc = device_private(self);
1799 int s;
1800
1801 s = spltty();
1802 memcpy(dest, &sc->sc_stats, sizeof(struct bt_stats));
1803
1804 if (flush)
1805 memset(&sc->sc_stats, 0, sizeof(struct bt_stats));
1806
1807 splx(s);
1808 }
1809
1810
1811 #ifdef BTH5_DEBUG
1812 static void
1813 bth5_packet_print(struct mbuf *m)
1814 {
1815 int i;
1816 uint8_t *p;
1817
1818 for ( ; m != NULL; m = m->m_next) {
1819 p = mtod(m, uint8_t *);
1820 for (i = 0; i < m->m_len; i++) {
1821 if (i % 16 == 0)
1822 printf(" ");
1823 printf(" %02x", *(p + i));
1824 if (i % 16 == 15)
1825 printf("\n");
1826 }
1827 printf("\n");
1828 }
1829 }
1830 #endif
1831