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