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 > 0 && 304 m_copyback2(m, sizeof(hci_cmd_hdr_t), len, buf, M_NOWAIT) != 0) { 305 m_freem(m); 306 return ENOMEM; 307 } 308 309 DPRINTFN(2, "(%s) opcode (%3.3x|%4.4x)\n", 310 device_get_nameunit(unit->hci_dev), 311 HCI_OGF(opcode), HCI_OCF(opcode)); 312 313 /* and send it on */ 314 if (unit->hci_num_cmd_pkts == 0) 315 IF_ENQUEUE(&unit->hci_cmdwait, m); 316 else 317 hci_output_cmd(unit, m); 318 319 return 0; 320 } 321 322 /* 323 * Incoming packet processing. Since the code is single threaded 324 * in any case (IPL_SOFTNET), we handle it all in one interrupt function 325 * picking our way through more important packets first so that hopefully 326 * we will never get clogged up with bulk data. 327 */ 328 void 329 hci_intr(void *arg) 330 { 331 struct hci_unit *unit = arg; 332 struct mbuf *m; 333 334 another: 335 lockmgr(&unit->hci_devlock, LK_EXCLUSIVE); 336 337 if (unit->hci_eventqlen > 0) { 338 IF_DEQUEUE(&unit->hci_eventq, m); 339 unit->hci_eventqlen--; 340 lockmgr(&unit->hci_devlock, LK_RELEASE); 341 342 KKASSERT(m != NULL); 343 344 DPRINTFN(10, "(%s) recv event, len = %d\n", 345 device_get_nameunit(unit->hci_dev), m->m_pkthdr.len); 346 347 m->m_flags |= IFF_LINK0; /* mark incoming packet */ 348 hci_mtap(m, unit); 349 hci_event(m, unit); 350 351 goto another; 352 } 353 354 if (unit->hci_scorxqlen > 0) { 355 IF_DEQUEUE(&unit->hci_scorxq, m); 356 unit->hci_scorxqlen--; 357 lockmgr(&unit->hci_devlock, LK_RELEASE); 358 KKASSERT(m != NULL); 359 360 DPRINTFN(10, "(%s) recv SCO, len = %d\n", 361 device_get_nameunit(unit->hci_dev), m->m_pkthdr.len); 362 363 m->m_flags |= IFF_LINK0; /* mark incoming packet */ 364 hci_mtap(m, unit); 365 hci_sco_recv(m, unit); 366 367 goto another; 368 } 369 370 if (unit->hci_aclrxqlen > 0) { 371 IF_DEQUEUE(&unit->hci_aclrxq, m); 372 unit->hci_aclrxqlen--; 373 lockmgr(&unit->hci_devlock, LK_RELEASE); 374 375 KKASSERT(m != NULL); 376 377 DPRINTFN(10, "(%s) recv ACL, len = %d\n", 378 device_get_nameunit(unit->hci_dev), m->m_pkthdr.len); 379 380 m->m_flags |= IFF_LINK0; /* mark incoming packet */ 381 hci_mtap(m, unit); 382 hci_acl_recv(m, unit); 383 384 goto another; 385 } 386 387 IF_DEQUEUE(&unit->hci_scodone, m); 388 if (m != NULL) { 389 struct hci_link *link; 390 lockmgr(&unit->hci_devlock, LK_RELEASE); 391 392 DPRINTFN(11, "(%s) complete SCO\n", 393 device_get_nameunit(unit->hci_dev)); 394 395 TAILQ_FOREACH(link, &unit->hci_links, hl_next) { 396 if (link == M_GETCTX(m, struct hci_link *)) { 397 hci_sco_complete(link, 1); 398 break; 399 } 400 } 401 402 unit->hci_num_sco_pkts++; 403 m_freem(m); 404 405 goto another; 406 } 407 408 lockmgr(&unit->hci_devlock, LK_RELEASE); 409 410 DPRINTFN(10, "done\n"); 411 } 412 413 /********************************************************************** 414 * 415 * IO routines 416 * 417 * input & complete routines will be called from device drivers, 418 * possibly in interrupt context. We return success or failure to 419 * enable proper accounting but we own the mbuf. 420 */ 421 422 int 423 hci_input_event(struct hci_unit *unit, struct mbuf *m) 424 { 425 int rv; 426 427 lockmgr(&unit->hci_devlock, LK_EXCLUSIVE); 428 429 if (unit->hci_eventqlen > hci_eventq_max) { 430 DPRINTF("(%s) dropped event packet.\n", 431 device_get_nameunit(unit->hci_dev)); 432 m_freem(m); 433 rv = 0; 434 } else { 435 unit->hci_eventqlen++; 436 IF_ENQUEUE(&unit->hci_eventq, m); 437 netisr_queue(NETISR_BLUETOOTH, m); 438 rv = 1; 439 } 440 lockmgr(&unit->hci_devlock, LK_RELEASE); 441 442 return rv; 443 } 444 445 int 446 hci_input_acl(struct hci_unit *unit, struct mbuf *m) 447 { 448 int rv; 449 450 lockmgr(&unit->hci_devlock, LK_EXCLUSIVE); 451 if (unit->hci_aclrxqlen > hci_aclrxq_max) { 452 DPRINTF("(%s) dropped ACL packet.\n", 453 device_get_nameunit(unit->hci_dev)); 454 m_freem(m); 455 rv = 0; 456 } else { 457 unit->hci_aclrxqlen++; 458 IF_ENQUEUE(&unit->hci_aclrxq, m); 459 netisr_queue(NETISR_BLUETOOTH, m); 460 rv = 1; 461 } 462 lockmgr(&unit->hci_devlock, LK_RELEASE); 463 464 return rv; 465 } 466 467 int 468 hci_input_sco(struct hci_unit *unit, struct mbuf *m) 469 { 470 int rv; 471 472 lockmgr(&unit->hci_devlock, LK_EXCLUSIVE); 473 if (unit->hci_scorxqlen > hci_scorxq_max) { 474 DPRINTF("(%s) dropped SCO packet.\n", 475 device_get_nameunit(unit->hci_dev)); 476 m_freem(m); 477 rv = 0; 478 } else { 479 unit->hci_scorxqlen++; 480 IF_ENQUEUE(&unit->hci_scorxq, m); 481 netisr_queue(NETISR_BLUETOOTH, m); 482 rv = 1; 483 } 484 lockmgr(&unit->hci_devlock, LK_RELEASE); 485 486 return rv; 487 } 488 489 void 490 hci_output_cmd(struct hci_unit *unit, struct mbuf *m) 491 { 492 void *arg; 493 494 hci_mtap(m, unit); 495 496 DPRINTFN(10, "(%s) num_cmd_pkts=%d\n", 497 device_get_nameunit(unit->hci_dev), unit->hci_num_cmd_pkts); 498 499 unit->hci_num_cmd_pkts--; 500 501 /* 502 * If context is set, this was from a HCI raw socket 503 * and a record needs to be dropped from the sockbuf. 504 */ 505 arg = M_GETCTX(m, void *); 506 if (arg != NULL) 507 hci_drop(arg); 508 509 (*unit->hci_if->output_cmd)(unit->hci_dev, m); 510 } 511 512 void 513 hci_output_acl(struct hci_unit *unit, struct mbuf *m) 514 { 515 hci_mtap(m, unit); 516 517 DPRINTFN(10, "(%s) num_acl_pkts=%d\n", 518 device_get_nameunit(unit->hci_dev), unit->hci_num_acl_pkts); 519 520 unit->hci_num_acl_pkts--; 521 522 (*unit->hci_if->output_acl)(unit->hci_dev, m); 523 } 524 525 void 526 hci_output_sco(struct hci_unit *unit, struct mbuf *m) 527 { 528 hci_mtap(m, unit); 529 530 DPRINTFN(10, "(%s) num_sco_pkts=%d\n", 531 device_get_nameunit(unit->hci_dev), unit->hci_num_sco_pkts); 532 533 unit->hci_num_sco_pkts--; 534 535 (*unit->hci_if->output_sco)(unit->hci_dev, m); 536 } 537 538 int 539 hci_complete_sco(struct hci_unit *unit, struct mbuf *m) 540 { 541 lockmgr(&unit->hci_devlock, LK_EXCLUSIVE); 542 IF_ENQUEUE(&unit->hci_scodone, m); 543 netisr_queue(NETISR_BLUETOOTH,m); 544 lockmgr(&unit->hci_devlock, LK_RELEASE); 545 546 return 1; 547 } 548