1/* $NetBSD: hci_unit.c,v 1.16 2021/08/07 16:19:18 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.16 2021/08/07 16:19:18 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 51struct hci_unit_list hci_unit_list = SIMPLEQ_HEAD_INITIALIZER(hci_unit_list); 52 53MALLOC_DEFINE(M_BLUETOOTH, "Bluetooth", "Bluetooth System Memory"); 54 55/* 56 * HCI Input Queue max lengths. 57 */ 58int hci_eventq_max = 20; 59int hci_aclrxq_max = 50; 60int 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 */ 67static 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 */ 81static void hci_intr (void *); 82 83struct hci_unit * 84hci_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 122void 123hci_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 137int 138hci_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 CFARGS(.iattr = "btbus")); 198 199 return 0; 200 201bad2: 202 (*unit->hci_if->disable)(unit->hci_dev); 203 unit->hci_flags &= ~BTF_RUNNING; 204bad1: 205 softint_disestablish(unit->hci_rxint); 206 unit->hci_rxint = NULL; 207 208 return err; 209} 210 211void 212hci_disable(struct hci_unit *unit) 213{ 214 struct hci_link *link, *next; 215 struct hci_memo *memo; 216 int acl; 217 218 if (unit->hci_bthub) { 219 device_t hub; 220 221 hub = unit->hci_bthub; 222 unit->hci_bthub = NULL; 223 224 mutex_exit(bt_lock); 225 config_detach(hub, DETACH_FORCE); 226 mutex_enter(bt_lock); 227 } 228 229 if (unit->hci_rxint) { 230 softint_disestablish(unit->hci_rxint); 231 unit->hci_rxint = NULL; 232 } 233 234 (*unit->hci_if->disable)(unit->hci_dev); 235 unit->hci_flags &= ~BTF_RUNNING; 236 237 /* 238 * close down any links, take care to close SCO first since 239 * they may depend on ACL links. 240 */ 241 for (acl = 0 ; acl < 2 ; acl++) { 242 next = TAILQ_FIRST(&unit->hci_links); 243 while ((link = next) != NULL) { 244 next = TAILQ_NEXT(link, hl_next); 245 if (acl || link->hl_type != HCI_LINK_ACL) 246 hci_link_free(link, ECONNABORTED); 247 } 248 } 249 250 while ((memo = LIST_FIRST(&unit->hci_memos)) != NULL) 251 hci_memo_free(memo); 252 253 /* (no need to hold hci_devlock, the driver is disabled) */ 254 255 MBUFQ_DRAIN(&unit->hci_eventq); 256 unit->hci_eventqlen = 0; 257 258 MBUFQ_DRAIN(&unit->hci_aclrxq); 259 unit->hci_aclrxqlen = 0; 260 261 MBUFQ_DRAIN(&unit->hci_scorxq); 262 unit->hci_scorxqlen = 0; 263 264 MBUFQ_DRAIN(&unit->hci_cmdwait); 265 MBUFQ_DRAIN(&unit->hci_scodone); 266} 267 268struct hci_unit * 269hci_unit_lookup(const bdaddr_t *addr) 270{ 271 struct hci_unit *unit; 272 273 SIMPLEQ_FOREACH(unit, &hci_unit_list, hci_next) { 274 if ((unit->hci_flags & BTF_UP) == 0) 275 continue; 276 277 if (bdaddr_same(&unit->hci_bdaddr, addr)) 278 break; 279 } 280 281 return unit; 282} 283 284/* 285 * update num_cmd_pkts and push on pending commands queue 286 */ 287void 288hci_num_cmds(struct hci_unit *unit, uint8_t num) 289{ 290 struct mbuf *m; 291 292 unit->hci_num_cmd_pkts = num; 293 294 while (unit->hci_num_cmd_pkts > 0 && MBUFQ_FIRST(&unit->hci_cmdwait)) { 295 MBUFQ_DEQUEUE(&unit->hci_cmdwait, m); 296 hci_output_cmd(unit, m); 297 } 298} 299 300/* 301 * construct and queue a HCI command packet 302 */ 303int 304hci_send_cmd(struct hci_unit *unit, uint16_t opcode, void *buf, uint8_t len) 305{ 306 struct mbuf *m; 307 hci_cmd_hdr_t *p; 308 309 KASSERT(unit != NULL); 310 311 m = m_gethdr(M_DONTWAIT, MT_DATA); 312 if (m == NULL) 313 return ENOMEM; 314 315 p = mtod(m, hci_cmd_hdr_t *); 316 p->type = HCI_CMD_PKT; 317 p->opcode = htole16(opcode); 318 p->length = len; 319 m->m_pkthdr.len = m->m_len = sizeof(hci_cmd_hdr_t); 320 321 if (len) { 322 KASSERT(buf != NULL); 323 324 m_copyback(m, sizeof(hci_cmd_hdr_t), len, buf); 325 if (m->m_pkthdr.len != (sizeof(hci_cmd_hdr_t) + len)) { 326 m_freem(m); 327 return ENOMEM; 328 } 329 } 330 331 DPRINTFN(2, "(%s) opcode (%3.3x|%4.4x)\n", device_xname(unit->hci_dev), 332 HCI_OGF(opcode), HCI_OCF(opcode)); 333 334 /* and send it on */ 335 if (unit->hci_num_cmd_pkts == 0) 336 MBUFQ_ENQUEUE(&unit->hci_cmdwait, m); 337 else 338 hci_output_cmd(unit, m); 339 340 return 0; 341} 342 343/* 344 * Incoming packet processing. Since the code is single threaded 345 * in any case (IPL_SOFTNET), we handle it all in one interrupt function 346 * picking our way through more important packets first so that hopefully 347 * we will never get clogged up with bulk data. 348 */ 349static void 350hci_intr(void *arg) 351{ 352 struct hci_unit *unit = arg; 353 struct mbuf *m; 354 355 mutex_enter(bt_lock); 356another: 357 mutex_enter(&unit->hci_devlock); 358 359 if (unit->hci_eventqlen > 0) { 360 MBUFQ_DEQUEUE(&unit->hci_eventq, m); 361 unit->hci_eventqlen--; 362 mutex_exit(&unit->hci_devlock); 363 364 KASSERT(m != NULL); 365 366 DPRINTFN(10, "(%s) recv event, len = %d\n", 367 device_xname(unit->hci_dev), m->m_pkthdr.len); 368 369 m->m_flags |= M_LINK0; /* mark incoming packet */ 370 hci_mtap(m, unit); 371 hci_event(m, unit); 372 373 goto another; 374 } 375 376 if (unit->hci_scorxqlen > 0) { 377 MBUFQ_DEQUEUE(&unit->hci_scorxq, m); 378 unit->hci_scorxqlen--; 379 mutex_exit(&unit->hci_devlock); 380 381 KASSERT(m != NULL); 382 383 DPRINTFN(10, "(%s) recv SCO, len = %d\n", 384 device_xname(unit->hci_dev), m->m_pkthdr.len); 385 386 m->m_flags |= M_LINK0; /* mark incoming packet */ 387 hci_mtap(m, unit); 388 hci_sco_recv(m, unit); 389 390 goto another; 391 } 392 393 if (unit->hci_aclrxqlen > 0) { 394 MBUFQ_DEQUEUE(&unit->hci_aclrxq, m); 395 unit->hci_aclrxqlen--; 396 mutex_exit(&unit->hci_devlock); 397 398 KASSERT(m != NULL); 399 400 DPRINTFN(10, "(%s) recv ACL, len = %d\n", 401 device_xname(unit->hci_dev), m->m_pkthdr.len); 402 403 m->m_flags |= M_LINK0; /* mark incoming packet */ 404 hci_mtap(m, unit); 405 hci_acl_recv(m, unit); 406 407 goto another; 408 } 409 410 MBUFQ_DEQUEUE(&unit->hci_scodone, m); 411 if (m != NULL) { 412 struct hci_link *link; 413 414 mutex_exit(&unit->hci_devlock); 415 416 DPRINTFN(11, "(%s) complete SCO\n", 417 device_xname(unit->hci_dev)); 418 419 TAILQ_FOREACH(link, &unit->hci_links, hl_next) { 420 if (link == M_GETCTX(m, struct hci_link *)) { 421 hci_sco_complete(link, 1); 422 break; 423 } 424 } 425 426 unit->hci_num_sco_pkts++; 427 m_freem(m); 428 429 goto another; 430 } 431 432 mutex_exit(&unit->hci_devlock); 433 mutex_exit(bt_lock); 434 435 DPRINTFN(10, "done\n"); 436} 437 438/********************************************************************** 439 * 440 * IO routines 441 * 442 * input & complete routines will be called from device drivers, 443 * possibly in interrupt context. We return success or failure to 444 * enable proper accounting but we own the mbuf. 445 */ 446 447bool 448hci_input_event(struct hci_unit *unit, struct mbuf *m) 449{ 450 bool rv; 451 452 mutex_enter(&unit->hci_devlock); 453 454 if (unit->hci_eventqlen > hci_eventq_max || unit->hci_rxint == NULL) { 455 DPRINTF("(%s) dropped event packet.\n", device_xname(unit->hci_dev)); 456 m_freem(m); 457 rv = false; 458 } else { 459 unit->hci_eventqlen++; 460 MBUFQ_ENQUEUE(&unit->hci_eventq, m); 461 softint_schedule(unit->hci_rxint); 462 rv = true; 463 } 464 465 mutex_exit(&unit->hci_devlock); 466 return rv; 467} 468 469bool 470hci_input_acl(struct hci_unit *unit, struct mbuf *m) 471{ 472 bool rv; 473 474 mutex_enter(&unit->hci_devlock); 475 476 if (unit->hci_aclrxqlen > hci_aclrxq_max || unit->hci_rxint == NULL) { 477 DPRINTF("(%s) dropped ACL packet.\n", device_xname(unit->hci_dev)); 478 m_freem(m); 479 rv = false; 480 } else { 481 unit->hci_aclrxqlen++; 482 MBUFQ_ENQUEUE(&unit->hci_aclrxq, m); 483 softint_schedule(unit->hci_rxint); 484 rv = true; 485 } 486 487 mutex_exit(&unit->hci_devlock); 488 return rv; 489} 490 491bool 492hci_input_sco(struct hci_unit *unit, struct mbuf *m) 493{ 494 bool rv; 495 496 mutex_enter(&unit->hci_devlock); 497 498 if (unit->hci_scorxqlen > hci_scorxq_max || unit->hci_rxint == NULL) { 499 DPRINTF("(%s) dropped SCO packet.\n", device_xname(unit->hci_dev)); 500 m_freem(m); 501 rv = false; 502 } else { 503 unit->hci_scorxqlen++; 504 MBUFQ_ENQUEUE(&unit->hci_scorxq, m); 505 softint_schedule(unit->hci_rxint); 506 rv = true; 507 } 508 509 mutex_exit(&unit->hci_devlock); 510 return rv; 511} 512 513void 514hci_output_cmd(struct hci_unit *unit, struct mbuf *m) 515{ 516 void *arg; 517 518 hci_mtap(m, unit); 519 520 DPRINTFN(10, "(%s) num_cmd_pkts=%d\n", device_xname(unit->hci_dev), 521 unit->hci_num_cmd_pkts); 522 523 unit->hci_num_cmd_pkts--; 524 525 /* 526 * If context is set, this was from a HCI raw socket 527 * and a record needs to be dropped from the sockbuf. 528 */ 529 arg = M_GETCTX(m, void *); 530 if (arg != NULL) 531 hci_drop(arg); 532 533 (*unit->hci_if->output_cmd)(unit->hci_dev, m); 534} 535 536void 537hci_output_acl(struct hci_unit *unit, struct mbuf *m) 538{ 539 540 hci_mtap(m, unit); 541 542 DPRINTFN(10, "(%s) num_acl_pkts=%d\n", device_xname(unit->hci_dev), 543 unit->hci_num_acl_pkts); 544 545 unit->hci_num_acl_pkts--; 546 (*unit->hci_if->output_acl)(unit->hci_dev, m); 547} 548 549void 550hci_output_sco(struct hci_unit *unit, struct mbuf *m) 551{ 552 553 hci_mtap(m, unit); 554 555 DPRINTFN(10, "(%s) num_sco_pkts=%d\n", device_xname(unit->hci_dev), 556 unit->hci_num_sco_pkts); 557 558 unit->hci_num_sco_pkts--; 559 (*unit->hci_if->output_sco)(unit->hci_dev, m); 560} 561 562bool 563hci_complete_sco(struct hci_unit *unit, struct mbuf *m) 564{ 565 566 if (unit->hci_rxint == NULL) { 567 DPRINTFN(10, "(%s) complete SCO!\n", device_xname(unit->hci_dev)); 568 m_freem(m); 569 return false; 570 } 571 572 mutex_enter(&unit->hci_devlock); 573 574 MBUFQ_ENQUEUE(&unit->hci_scodone, m); 575 softint_schedule(unit->hci_rxint); 576 577 mutex_exit(&unit->hci_devlock); 578 return true; 579} 580