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