1 /* $NetBSD: hci_unit.c,v 1.15 2021/04/24 23:37:01 thorpej Exp $ */ 2 3 /*- 4 * Copyright (c) 2005 Iain Hibbert. 5 * Copyright (c) 2006 Itronix Inc. 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 3. The name of Itronix Inc. may not be used to endorse 17 * or promote products derived from this software without specific 18 * prior written permission. 19 * 20 * THIS SOFTWARE IS PROVIDED BY ITRONIX INC. ``AS IS'' AND 21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 22 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 23 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ITRONIX INC. BE LIABLE FOR ANY 24 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 25 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 26 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 27 * ON ANY THEORY OF LIABILITY, WHETHER IN 28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 29 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 30 * POSSIBILITY OF SUCH DAMAGE. 31 */ 32 33 #include <sys/cdefs.h> 34 __KERNEL_RCSID(0, "$NetBSD: hci_unit.c,v 1.15 2021/04/24 23:37:01 thorpej Exp $"); 35 36 #include <sys/param.h> 37 #include <sys/conf.h> 38 #include <sys/device.h> 39 #include <sys/kernel.h> 40 #include <sys/malloc.h> 41 #include <sys/mbuf.h> 42 #include <sys/proc.h> 43 #include <sys/queue.h> 44 #include <sys/systm.h> 45 #include <sys/intr.h> 46 #include <sys/socketvar.h> 47 48 #include <netbt/bluetooth.h> 49 #include <netbt/hci.h> 50 51 struct hci_unit_list hci_unit_list = SIMPLEQ_HEAD_INITIALIZER(hci_unit_list); 52 53 MALLOC_DEFINE(M_BLUETOOTH, "Bluetooth", "Bluetooth System Memory"); 54 55 /* 56 * HCI Input Queue max lengths. 57 */ 58 int hci_eventq_max = 20; 59 int hci_aclrxq_max = 50; 60 int hci_scorxq_max = 50; 61 62 /* 63 * This is the default minimum command set supported by older 64 * devices. Anything conforming to 1.2 spec or later will get 65 * updated during init. 66 */ 67 static const uint8_t hci_cmds_v10[HCI_COMMANDS_SIZE] = { 68 0xff, 0xff, 0xff, 0x01, 0xfe, 0xff, 0xff, 0xff, 69 0xff, 0xff, 0xff, 0x7f, 0x32, 0x03, 0xb8, 0xfe, 70 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 71 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 72 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 73 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 74 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 75 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 76 }; 77 78 /* 79 * bluetooth unit functions 80 */ 81 static void hci_intr (void *); 82 83 struct hci_unit * 84 hci_attach_pcb(const struct hci_if *hci_if, device_t dev, uint16_t flags) 85 { 86 struct hci_unit *unit; 87 88 KASSERT(dev != NULL); 89 KASSERT(hci_if->enable != NULL); 90 KASSERT(hci_if->disable != NULL); 91 KASSERT(hci_if->output_cmd != NULL); 92 KASSERT(hci_if->output_acl != NULL); 93 KASSERT(hci_if->output_sco != NULL); 94 KASSERT(hci_if->get_stats != NULL); 95 96 unit = malloc(sizeof(struct hci_unit), M_BLUETOOTH, M_ZERO | M_WAITOK); 97 KASSERT(unit != NULL); 98 99 unit->hci_dev = dev; 100 unit->hci_if = hci_if; 101 unit->hci_flags = flags; 102 103 mutex_init(&unit->hci_devlock, MUTEX_DRIVER, hci_if->ipl); 104 cv_init(&unit->hci_init, "hci_init"); 105 106 MBUFQ_INIT(&unit->hci_eventq); 107 MBUFQ_INIT(&unit->hci_aclrxq); 108 MBUFQ_INIT(&unit->hci_scorxq); 109 MBUFQ_INIT(&unit->hci_cmdwait); 110 MBUFQ_INIT(&unit->hci_scodone); 111 112 TAILQ_INIT(&unit->hci_links); 113 LIST_INIT(&unit->hci_memos); 114 115 mutex_enter(bt_lock); 116 SIMPLEQ_INSERT_TAIL(&hci_unit_list, unit, hci_next); 117 mutex_exit(bt_lock); 118 119 return unit; 120 } 121 122 void 123 hci_detach_pcb(struct hci_unit *unit) 124 { 125 126 mutex_enter(bt_lock); 127 hci_disable(unit); 128 129 SIMPLEQ_REMOVE(&hci_unit_list, unit, hci_unit, hci_next); 130 mutex_exit(bt_lock); 131 132 cv_destroy(&unit->hci_init); 133 mutex_destroy(&unit->hci_devlock); 134 free(unit, M_BLUETOOTH); 135 } 136 137 int 138 hci_enable(struct hci_unit *unit) 139 { 140 int err; 141 142 /* 143 * Bluetooth spec says that a device can accept one 144 * command on power up until they send a Command Status 145 * or Command Complete event with more information, but 146 * it seems that some devices cant and prefer to send a 147 * No-op Command Status packet when they are ready. 148 */ 149 unit->hci_num_cmd_pkts = (unit->hci_flags & BTF_POWER_UP_NOOP) ? 0 : 1; 150 unit->hci_num_acl_pkts = 0; 151 unit->hci_num_sco_pkts = 0; 152 153 /* 154 * only allow the basic packet types until 155 * the features report is in 156 */ 157 unit->hci_acl_mask = HCI_PKT_DM1 | HCI_PKT_DH1; 158 unit->hci_packet_type = unit->hci_acl_mask; 159 160 memcpy(unit->hci_cmds, hci_cmds_v10, HCI_COMMANDS_SIZE); 161 162 unit->hci_rxint = softint_establish(SOFTINT_NET, &hci_intr, unit); 163 if (unit->hci_rxint == NULL) 164 return EIO; 165 166 err = (*unit->hci_if->enable)(unit->hci_dev); 167 if (err) 168 goto bad1; 169 170 unit->hci_flags |= BTF_RUNNING; 171 172 /* 173 * Reset the device, this will trigger initialisation 174 * and wake us up. 175 */ 176 unit->hci_flags |= BTF_INIT; 177 178 err = hci_send_cmd(unit, HCI_CMD_RESET, NULL, 0); 179 if (err) 180 goto bad2; 181 182 while (unit->hci_flags & BTF_INIT) { 183 err = cv_timedwait_sig(&unit->hci_init, bt_lock, 5 * hz); 184 if (err) 185 goto bad2; 186 187 /* XXX 188 * "What If", while we were sleeping, the device 189 * was removed and detached? Ho Hum. 190 */ 191 } 192 193 /* 194 * Attach Bluetooth Device Hub 195 */ 196 unit->hci_bthub = config_found(unit->hci_dev, &unit->hci_bdaddr, NULL, 197 CFARG_IATTR, "btbus", 198 CFARG_EOL); 199 200 return 0; 201 202 bad2: 203 (*unit->hci_if->disable)(unit->hci_dev); 204 unit->hci_flags &= ~BTF_RUNNING; 205 bad1: 206 softint_disestablish(unit->hci_rxint); 207 unit->hci_rxint = NULL; 208 209 return err; 210 } 211 212 void 213 hci_disable(struct hci_unit *unit) 214 { 215 struct hci_link *link, *next; 216 struct hci_memo *memo; 217 int acl; 218 219 if (unit->hci_bthub) { 220 device_t hub; 221 222 hub = unit->hci_bthub; 223 unit->hci_bthub = NULL; 224 225 mutex_exit(bt_lock); 226 config_detach(hub, DETACH_FORCE); 227 mutex_enter(bt_lock); 228 } 229 230 if (unit->hci_rxint) { 231 softint_disestablish(unit->hci_rxint); 232 unit->hci_rxint = NULL; 233 } 234 235 (*unit->hci_if->disable)(unit->hci_dev); 236 unit->hci_flags &= ~BTF_RUNNING; 237 238 /* 239 * close down any links, take care to close SCO first since 240 * they may depend on ACL links. 241 */ 242 for (acl = 0 ; acl < 2 ; acl++) { 243 next = TAILQ_FIRST(&unit->hci_links); 244 while ((link = next) != NULL) { 245 next = TAILQ_NEXT(link, hl_next); 246 if (acl || link->hl_type != HCI_LINK_ACL) 247 hci_link_free(link, ECONNABORTED); 248 } 249 } 250 251 while ((memo = LIST_FIRST(&unit->hci_memos)) != NULL) 252 hci_memo_free(memo); 253 254 /* (no need to hold hci_devlock, the driver is disabled) */ 255 256 MBUFQ_DRAIN(&unit->hci_eventq); 257 unit->hci_eventqlen = 0; 258 259 MBUFQ_DRAIN(&unit->hci_aclrxq); 260 unit->hci_aclrxqlen = 0; 261 262 MBUFQ_DRAIN(&unit->hci_scorxq); 263 unit->hci_scorxqlen = 0; 264 265 MBUFQ_DRAIN(&unit->hci_cmdwait); 266 MBUFQ_DRAIN(&unit->hci_scodone); 267 } 268 269 struct hci_unit * 270 hci_unit_lookup(const bdaddr_t *addr) 271 { 272 struct hci_unit *unit; 273 274 SIMPLEQ_FOREACH(unit, &hci_unit_list, hci_next) { 275 if ((unit->hci_flags & BTF_UP) == 0) 276 continue; 277 278 if (bdaddr_same(&unit->hci_bdaddr, addr)) 279 break; 280 } 281 282 return unit; 283 } 284 285 /* 286 * update num_cmd_pkts and push on pending commands queue 287 */ 288 void 289 hci_num_cmds(struct hci_unit *unit, uint8_t num) 290 { 291 struct mbuf *m; 292 293 unit->hci_num_cmd_pkts = num; 294 295 while (unit->hci_num_cmd_pkts > 0 && MBUFQ_FIRST(&unit->hci_cmdwait)) { 296 MBUFQ_DEQUEUE(&unit->hci_cmdwait, m); 297 hci_output_cmd(unit, m); 298 } 299 } 300 301 /* 302 * construct and queue a HCI command packet 303 */ 304 int 305 hci_send_cmd(struct hci_unit *unit, uint16_t opcode, void *buf, uint8_t len) 306 { 307 struct mbuf *m; 308 hci_cmd_hdr_t *p; 309 310 KASSERT(unit != NULL); 311 312 m = m_gethdr(M_DONTWAIT, MT_DATA); 313 if (m == NULL) 314 return ENOMEM; 315 316 p = mtod(m, hci_cmd_hdr_t *); 317 p->type = HCI_CMD_PKT; 318 p->opcode = htole16(opcode); 319 p->length = len; 320 m->m_pkthdr.len = m->m_len = sizeof(hci_cmd_hdr_t); 321 322 if (len) { 323 KASSERT(buf != NULL); 324 325 m_copyback(m, sizeof(hci_cmd_hdr_t), len, buf); 326 if (m->m_pkthdr.len != (sizeof(hci_cmd_hdr_t) + len)) { 327 m_freem(m); 328 return ENOMEM; 329 } 330 } 331 332 DPRINTFN(2, "(%s) opcode (%3.3x|%4.4x)\n", device_xname(unit->hci_dev), 333 HCI_OGF(opcode), HCI_OCF(opcode)); 334 335 /* and send it on */ 336 if (unit->hci_num_cmd_pkts == 0) 337 MBUFQ_ENQUEUE(&unit->hci_cmdwait, m); 338 else 339 hci_output_cmd(unit, m); 340 341 return 0; 342 } 343 344 /* 345 * Incoming packet processing. Since the code is single threaded 346 * in any case (IPL_SOFTNET), we handle it all in one interrupt function 347 * picking our way through more important packets first so that hopefully 348 * we will never get clogged up with bulk data. 349 */ 350 static void 351 hci_intr(void *arg) 352 { 353 struct hci_unit *unit = arg; 354 struct mbuf *m; 355 356 mutex_enter(bt_lock); 357 another: 358 mutex_enter(&unit->hci_devlock); 359 360 if (unit->hci_eventqlen > 0) { 361 MBUFQ_DEQUEUE(&unit->hci_eventq, m); 362 unit->hci_eventqlen--; 363 mutex_exit(&unit->hci_devlock); 364 365 KASSERT(m != NULL); 366 367 DPRINTFN(10, "(%s) recv event, len = %d\n", 368 device_xname(unit->hci_dev), m->m_pkthdr.len); 369 370 m->m_flags |= M_LINK0; /* mark incoming packet */ 371 hci_mtap(m, unit); 372 hci_event(m, unit); 373 374 goto another; 375 } 376 377 if (unit->hci_scorxqlen > 0) { 378 MBUFQ_DEQUEUE(&unit->hci_scorxq, m); 379 unit->hci_scorxqlen--; 380 mutex_exit(&unit->hci_devlock); 381 382 KASSERT(m != NULL); 383 384 DPRINTFN(10, "(%s) recv SCO, len = %d\n", 385 device_xname(unit->hci_dev), m->m_pkthdr.len); 386 387 m->m_flags |= M_LINK0; /* mark incoming packet */ 388 hci_mtap(m, unit); 389 hci_sco_recv(m, unit); 390 391 goto another; 392 } 393 394 if (unit->hci_aclrxqlen > 0) { 395 MBUFQ_DEQUEUE(&unit->hci_aclrxq, m); 396 unit->hci_aclrxqlen--; 397 mutex_exit(&unit->hci_devlock); 398 399 KASSERT(m != NULL); 400 401 DPRINTFN(10, "(%s) recv ACL, len = %d\n", 402 device_xname(unit->hci_dev), m->m_pkthdr.len); 403 404 m->m_flags |= M_LINK0; /* mark incoming packet */ 405 hci_mtap(m, unit); 406 hci_acl_recv(m, unit); 407 408 goto another; 409 } 410 411 MBUFQ_DEQUEUE(&unit->hci_scodone, m); 412 if (m != NULL) { 413 struct hci_link *link; 414 415 mutex_exit(&unit->hci_devlock); 416 417 DPRINTFN(11, "(%s) complete SCO\n", 418 device_xname(unit->hci_dev)); 419 420 TAILQ_FOREACH(link, &unit->hci_links, hl_next) { 421 if (link == M_GETCTX(m, struct hci_link *)) { 422 hci_sco_complete(link, 1); 423 break; 424 } 425 } 426 427 unit->hci_num_sco_pkts++; 428 m_freem(m); 429 430 goto another; 431 } 432 433 mutex_exit(&unit->hci_devlock); 434 mutex_exit(bt_lock); 435 436 DPRINTFN(10, "done\n"); 437 } 438 439 /********************************************************************** 440 * 441 * IO routines 442 * 443 * input & complete routines will be called from device drivers, 444 * possibly in interrupt context. We return success or failure to 445 * enable proper accounting but we own the mbuf. 446 */ 447 448 bool 449 hci_input_event(struct hci_unit *unit, struct mbuf *m) 450 { 451 bool rv; 452 453 mutex_enter(&unit->hci_devlock); 454 455 if (unit->hci_eventqlen > hci_eventq_max || unit->hci_rxint == NULL) { 456 DPRINTF("(%s) dropped event packet.\n", device_xname(unit->hci_dev)); 457 m_freem(m); 458 rv = false; 459 } else { 460 unit->hci_eventqlen++; 461 MBUFQ_ENQUEUE(&unit->hci_eventq, m); 462 softint_schedule(unit->hci_rxint); 463 rv = true; 464 } 465 466 mutex_exit(&unit->hci_devlock); 467 return rv; 468 } 469 470 bool 471 hci_input_acl(struct hci_unit *unit, struct mbuf *m) 472 { 473 bool rv; 474 475 mutex_enter(&unit->hci_devlock); 476 477 if (unit->hci_aclrxqlen > hci_aclrxq_max || unit->hci_rxint == NULL) { 478 DPRINTF("(%s) dropped ACL packet.\n", device_xname(unit->hci_dev)); 479 m_freem(m); 480 rv = false; 481 } else { 482 unit->hci_aclrxqlen++; 483 MBUFQ_ENQUEUE(&unit->hci_aclrxq, m); 484 softint_schedule(unit->hci_rxint); 485 rv = true; 486 } 487 488 mutex_exit(&unit->hci_devlock); 489 return rv; 490 } 491 492 bool 493 hci_input_sco(struct hci_unit *unit, struct mbuf *m) 494 { 495 bool rv; 496 497 mutex_enter(&unit->hci_devlock); 498 499 if (unit->hci_scorxqlen > hci_scorxq_max || unit->hci_rxint == NULL) { 500 DPRINTF("(%s) dropped SCO packet.\n", device_xname(unit->hci_dev)); 501 m_freem(m); 502 rv = false; 503 } else { 504 unit->hci_scorxqlen++; 505 MBUFQ_ENQUEUE(&unit->hci_scorxq, m); 506 softint_schedule(unit->hci_rxint); 507 rv = true; 508 } 509 510 mutex_exit(&unit->hci_devlock); 511 return rv; 512 } 513 514 void 515 hci_output_cmd(struct hci_unit *unit, struct mbuf *m) 516 { 517 void *arg; 518 519 hci_mtap(m, unit); 520 521 DPRINTFN(10, "(%s) num_cmd_pkts=%d\n", device_xname(unit->hci_dev), 522 unit->hci_num_cmd_pkts); 523 524 unit->hci_num_cmd_pkts--; 525 526 /* 527 * If context is set, this was from a HCI raw socket 528 * and a record needs to be dropped from the sockbuf. 529 */ 530 arg = M_GETCTX(m, void *); 531 if (arg != NULL) 532 hci_drop(arg); 533 534 (*unit->hci_if->output_cmd)(unit->hci_dev, m); 535 } 536 537 void 538 hci_output_acl(struct hci_unit *unit, struct mbuf *m) 539 { 540 541 hci_mtap(m, unit); 542 543 DPRINTFN(10, "(%s) num_acl_pkts=%d\n", device_xname(unit->hci_dev), 544 unit->hci_num_acl_pkts); 545 546 unit->hci_num_acl_pkts--; 547 (*unit->hci_if->output_acl)(unit->hci_dev, m); 548 } 549 550 void 551 hci_output_sco(struct hci_unit *unit, struct mbuf *m) 552 { 553 554 hci_mtap(m, unit); 555 556 DPRINTFN(10, "(%s) num_sco_pkts=%d\n", device_xname(unit->hci_dev), 557 unit->hci_num_sco_pkts); 558 559 unit->hci_num_sco_pkts--; 560 (*unit->hci_if->output_sco)(unit->hci_dev, m); 561 } 562 563 bool 564 hci_complete_sco(struct hci_unit *unit, struct mbuf *m) 565 { 566 567 if (unit->hci_rxint == NULL) { 568 DPRINTFN(10, "(%s) complete SCO!\n", device_xname(unit->hci_dev)); 569 m_freem(m); 570 return false; 571 } 572 573 mutex_enter(&unit->hci_devlock); 574 575 MBUFQ_ENQUEUE(&unit->hci_scodone, m); 576 softint_schedule(unit->hci_rxint); 577 578 mutex_exit(&unit->hci_devlock); 579 return true; 580 } 581