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