Home | History | Annotate | Line # | Download | only in netbt
hci_unit.c revision 1.9.6.1
      1 /*	$NetBSD: hci_unit.c,v 1.9.6.1 2008/04/03 12:43:08 mjf 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.9.6.1 2008/04/03 12:43:08 mjf 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 
     47 #include <netbt/bluetooth.h>
     48 #include <netbt/hci.h>
     49 
     50 struct hci_unit_list hci_unit_list = SIMPLEQ_HEAD_INITIALIZER(hci_unit_list);
     51 
     52 MALLOC_DEFINE(M_BLUETOOTH, "Bluetooth", "Bluetooth System Memory");
     53 
     54 /*
     55  * HCI Input Queue max lengths.
     56  */
     57 int hci_eventq_max = 20;
     58 int hci_aclrxq_max = 50;
     59 int hci_scorxq_max = 50;
     60 
     61 /*
     62  * This is the default minimum command set supported by older
     63  * devices. Anything conforming to 1.2 spec or later will get
     64  * updated during init.
     65  */
     66 static const uint8_t hci_cmds_v10[HCI_COMMANDS_SIZE] = {
     67 	0xff, 0xff, 0xff, 0x01, 0xfe, 0xff, 0xff, 0xff,
     68 	0xff, 0xff, 0xff, 0x7f, 0x32, 0x03, 0xb8, 0xfe,
     69 	0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     70 	0x00, 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 };
     76 
     77 /*
     78  * bluetooth unit functions
     79  */
     80 static void hci_intr (void *);
     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 	int s;
     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 
    105 	MBUFQ_INIT(&unit->hci_eventq);
    106 	MBUFQ_INIT(&unit->hci_aclrxq);
    107 	MBUFQ_INIT(&unit->hci_scorxq);
    108 	MBUFQ_INIT(&unit->hci_cmdwait);
    109 	MBUFQ_INIT(&unit->hci_scodone);
    110 
    111 	TAILQ_INIT(&unit->hci_links);
    112 	LIST_INIT(&unit->hci_memos);
    113 
    114 	s = splsoftnet();
    115 	SIMPLEQ_INSERT_TAIL(&hci_unit_list, unit, hci_next);
    116 	splx(s);
    117 
    118 	return unit;
    119 }
    120 
    121 void
    122 hci_detach(struct hci_unit *unit)
    123 {
    124 	int s;
    125 
    126 	s = splsoftnet();
    127 	hci_disable(unit);
    128 
    129 	SIMPLEQ_REMOVE(&hci_unit_list, unit, hci_unit, hci_next);
    130 	splx(s);
    131 
    132 	mutex_destroy(&unit->hci_devlock);
    133 	free(unit, M_BLUETOOTH);
    134 }
    135 
    136 int
    137 hci_enable(struct hci_unit *unit)
    138 {
    139 	int err;
    140 
    141 	/*
    142 	 * Bluetooth spec says that a device can accept one
    143 	 * command on power up until they send a Command Status
    144 	 * or Command Complete event with more information, but
    145 	 * it seems that some devices cant and prefer to send a
    146 	 * No-op Command Status packet when they are ready.
    147 	 */
    148 	unit->hci_num_cmd_pkts = (unit->hci_flags & BTF_POWER_UP_NOOP) ? 0 : 1;
    149 	unit->hci_num_acl_pkts = 0;
    150 	unit->hci_num_sco_pkts = 0;
    151 
    152 	/*
    153 	 * only allow the basic packet types until
    154 	 * the features report is in
    155 	 */
    156 	unit->hci_acl_mask = HCI_PKT_DM1 | HCI_PKT_DH1;
    157 	unit->hci_packet_type = unit->hci_acl_mask;
    158 
    159 	memcpy(unit->hci_cmds, hci_cmds_v10, HCI_COMMANDS_SIZE);
    160 
    161 	unit->hci_rxint = softint_establish(SOFTINT_NET, &hci_intr, unit);
    162 	if (unit->hci_rxint == NULL)
    163 		return EIO;
    164 
    165 	err = (*unit->hci_if->enable)(unit->hci_dev);
    166 	if (err)
    167 		goto bad1;
    168 
    169 	unit->hci_flags |= BTF_RUNNING;
    170 
    171 	/*
    172 	 * Reset the device, this will trigger initialisation
    173 	 * and wake us up.
    174 	 */
    175 	unit->hci_flags |= BTF_INIT;
    176 
    177 	err = hci_send_cmd(unit, HCI_CMD_RESET, NULL, 0);
    178 	if (err)
    179 		goto bad2;
    180 
    181 	while (unit->hci_flags & BTF_INIT) {
    182 		err = tsleep(unit, PWAIT | PCATCH, __func__, 5 * hz);
    183 		if (err)
    184 			goto bad2;
    185 
    186 		/* XXX
    187 		 * "What If", while we were sleeping, the device
    188 		 * was removed and detached? Ho Hum.
    189 		 */
    190 	}
    191 
    192 	/*
    193 	 * Attach Bluetooth Device Hub
    194 	 */
    195 	unit->hci_bthub = config_found_ia(unit->hci_dev,
    196 					  "btbus", &unit->hci_bdaddr, NULL);
    197 
    198 	return 0;
    199 
    200 bad2:
    201 	(*unit->hci_if->disable)(unit->hci_dev);
    202 	unit->hci_flags &= ~BTF_RUNNING;
    203 bad1:
    204 	softint_disestablish(unit->hci_rxint);
    205 	unit->hci_rxint = NULL;
    206 
    207 	return err;
    208 }
    209 
    210 void
    211 hci_disable(struct hci_unit *unit)
    212 {
    213 	struct hci_link *link, *next;
    214 	struct hci_memo *memo;
    215 	int acl;
    216 
    217 	if (unit->hci_bthub) {
    218 		config_detach(unit->hci_bthub, DETACH_FORCE);
    219 		unit->hci_bthub = NULL;
    220 	}
    221 
    222 	if (unit->hci_rxint) {
    223 		softint_disestablish(unit->hci_rxint);
    224 		unit->hci_rxint = NULL;
    225 	}
    226 
    227 	(*unit->hci_if->disable)(unit->hci_dev);
    228 	unit->hci_flags &= ~BTF_RUNNING;
    229 
    230 	/*
    231 	 * close down any links, take care to close SCO first since
    232 	 * they may depend on ACL links.
    233 	 */
    234 	for (acl = 0 ; acl < 2 ; acl++) {
    235 		next = TAILQ_FIRST(&unit->hci_links);
    236 		while ((link = next) != NULL) {
    237 			next = TAILQ_NEXT(link, hl_next);
    238 			if (acl || link->hl_type != HCI_LINK_ACL)
    239 				hci_link_free(link, ECONNABORTED);
    240 		}
    241 	}
    242 
    243 	while ((memo = LIST_FIRST(&unit->hci_memos)) != NULL)
    244 		hci_memo_free(memo);
    245 
    246 	/* (no need to hold hci_devlock, the driver is disabled) */
    247 
    248 	MBUFQ_DRAIN(&unit->hci_eventq);
    249 	unit->hci_eventqlen = 0;
    250 
    251 	MBUFQ_DRAIN(&unit->hci_aclrxq);
    252 	unit->hci_aclrxqlen = 0;
    253 
    254 	MBUFQ_DRAIN(&unit->hci_scorxq);
    255 	unit->hci_scorxqlen = 0;
    256 
    257 	MBUFQ_DRAIN(&unit->hci_cmdwait);
    258 	MBUFQ_DRAIN(&unit->hci_scodone);
    259 }
    260 
    261 struct hci_unit *
    262 hci_unit_lookup(bdaddr_t *addr)
    263 {
    264 	struct hci_unit *unit;
    265 
    266 	SIMPLEQ_FOREACH(unit, &hci_unit_list, hci_next) {
    267 		if ((unit->hci_flags & BTF_UP) == 0)
    268 			continue;
    269 
    270 		if (bdaddr_same(&unit->hci_bdaddr, addr))
    271 			break;
    272 	}
    273 
    274 	return unit;
    275 }
    276 
    277 /*
    278  * update num_cmd_pkts and push on pending commands queue
    279  */
    280 void
    281 hci_num_cmds(struct hci_unit *unit, uint8_t num)
    282 {
    283 	struct mbuf *m;
    284 
    285 	unit->hci_num_cmd_pkts = num;
    286 
    287 	while (unit->hci_num_cmd_pkts > 0 && MBUFQ_FIRST(&unit->hci_cmdwait)) {
    288 		MBUFQ_DEQUEUE(&unit->hci_cmdwait, m);
    289 		hci_output_cmd(unit, m);
    290 	}
    291 }
    292 
    293 /*
    294  * construct and queue a HCI command packet
    295  */
    296 int
    297 hci_send_cmd(struct hci_unit *unit, uint16_t opcode, void *buf, uint8_t len)
    298 {
    299 	struct mbuf *m;
    300 	hci_cmd_hdr_t *p;
    301 
    302 	KASSERT(unit != NULL);
    303 
    304 	m = m_gethdr(M_DONTWAIT, MT_DATA);
    305 	if (m == NULL)
    306 		return ENOMEM;
    307 
    308 	p = mtod(m, hci_cmd_hdr_t *);
    309 	p->type = HCI_CMD_PKT;
    310 	p->opcode = htole16(opcode);
    311 	p->length = len;
    312 	m->m_pkthdr.len = m->m_len = sizeof(hci_cmd_hdr_t);
    313 
    314 	if (len) {
    315 		KASSERT(buf != NULL);
    316 
    317 		m_copyback(m, sizeof(hci_cmd_hdr_t), len, buf);
    318 		if (m->m_pkthdr.len != (sizeof(hci_cmd_hdr_t) + len)) {
    319 			m_freem(m);
    320 			return ENOMEM;
    321 		}
    322 	}
    323 
    324 	DPRINTFN(2, "(%s) opcode (%3.3x|%4.4x)\n", device_xname(unit->hci_dev),
    325 		HCI_OGF(opcode), HCI_OCF(opcode));
    326 
    327 	/* and send it on */
    328 	if (unit->hci_num_cmd_pkts == 0)
    329 		MBUFQ_ENQUEUE(&unit->hci_cmdwait, m);
    330 	else
    331 		hci_output_cmd(unit, m);
    332 
    333 	return 0;
    334 }
    335 
    336 /*
    337  * Incoming packet processing. Since the code is single threaded
    338  * in any case (IPL_SOFTNET), we handle it all in one interrupt function
    339  * picking our way through more important packets first so that hopefully
    340  * we will never get clogged up with bulk data.
    341  */
    342 static void
    343 hci_intr(void *arg)
    344 {
    345 	struct hci_unit *unit = arg;
    346 	struct mbuf *m;
    347 
    348 another:
    349 	mutex_enter(&unit->hci_devlock);
    350 
    351 	if (unit->hci_eventqlen > 0) {
    352 		MBUFQ_DEQUEUE(&unit->hci_eventq, m);
    353 		unit->hci_eventqlen--;
    354 		mutex_exit(&unit->hci_devlock);
    355 
    356 		KASSERT(m != NULL);
    357 
    358 		DPRINTFN(10, "(%s) recv event, len = %d\n",
    359 				device_xname(unit->hci_dev), m->m_pkthdr.len);
    360 
    361 		m->m_flags |= M_LINK0;	/* mark incoming packet */
    362 		hci_mtap(m, unit);
    363 		hci_event(m, unit);
    364 
    365 		goto another;
    366 	}
    367 
    368 	if (unit->hci_scorxqlen > 0) {
    369 		MBUFQ_DEQUEUE(&unit->hci_scorxq, m);
    370 		unit->hci_scorxqlen--;
    371 		mutex_exit(&unit->hci_devlock);
    372 
    373 		KASSERT(m != NULL);
    374 
    375 		DPRINTFN(10, "(%s) recv SCO, len = %d\n",
    376 				device_xname(unit->hci_dev), m->m_pkthdr.len);
    377 
    378 		m->m_flags |= M_LINK0;	/* mark incoming packet */
    379 		hci_mtap(m, unit);
    380 		hci_sco_recv(m, unit);
    381 
    382 		goto another;
    383 	}
    384 
    385 	if (unit->hci_aclrxqlen > 0) {
    386 		MBUFQ_DEQUEUE(&unit->hci_aclrxq, m);
    387 		unit->hci_aclrxqlen--;
    388 		mutex_exit(&unit->hci_devlock);
    389 
    390 		KASSERT(m != NULL);
    391 
    392 		DPRINTFN(10, "(%s) recv ACL, len = %d\n",
    393 				device_xname(unit->hci_dev), m->m_pkthdr.len);
    394 
    395 		m->m_flags |= M_LINK0;	/* mark incoming packet */
    396 		hci_mtap(m, unit);
    397 		hci_acl_recv(m, unit);
    398 
    399 		goto another;
    400 	}
    401 
    402 	MBUFQ_DEQUEUE(&unit->hci_scodone, m);
    403 	if (m != NULL) {
    404 		struct hci_link *link;
    405 
    406 		mutex_exit(&unit->hci_devlock);
    407 
    408 		DPRINTFN(11, "(%s) complete SCO\n",
    409 				device_xname(unit->hci_dev));
    410 
    411 		TAILQ_FOREACH(link, &unit->hci_links, hl_next) {
    412 			if (link == M_GETCTX(m, struct hci_link *)) {
    413 				hci_sco_complete(link, 1);
    414 				break;
    415 			}
    416 		}
    417 
    418 		unit->hci_num_sco_pkts++;
    419 		m_freem(m);
    420 
    421 		goto another;
    422 	}
    423 
    424 	mutex_exit(&unit->hci_devlock);
    425 
    426 	DPRINTFN(10, "done\n");
    427 }
    428 
    429 /**********************************************************************
    430  *
    431  * IO routines
    432  *
    433  * input & complete routines will be called from device drivers,
    434  * possibly in interrupt context. We return success or failure to
    435  * enable proper accounting but we own the mbuf.
    436  */
    437 
    438 bool
    439 hci_input_event(struct hci_unit *unit, struct mbuf *m)
    440 {
    441 	bool rv;
    442 
    443 	mutex_enter(&unit->hci_devlock);
    444 
    445 	if (unit->hci_eventqlen > hci_eventq_max || unit->hci_rxint == NULL) {
    446 		DPRINTF("(%s) dropped event packet.\n", device_xname(unit->hci_dev));
    447 		m_freem(m);
    448 		rv = false;
    449 	} else {
    450 		unit->hci_eventqlen++;
    451 		MBUFQ_ENQUEUE(&unit->hci_eventq, m);
    452 		softint_schedule(unit->hci_rxint);
    453 		rv = true;
    454 	}
    455 
    456 	mutex_exit(&unit->hci_devlock);
    457 	return rv;
    458 }
    459 
    460 bool
    461 hci_input_acl(struct hci_unit *unit, struct mbuf *m)
    462 {
    463 	bool rv;
    464 
    465 	mutex_enter(&unit->hci_devlock);
    466 
    467 	if (unit->hci_aclrxqlen > hci_aclrxq_max || unit->hci_rxint == NULL) {
    468 		DPRINTF("(%s) dropped ACL packet.\n", device_xname(unit->hci_dev));
    469 		m_freem(m);
    470 		rv = false;
    471 	} else {
    472 		unit->hci_aclrxqlen++;
    473 		MBUFQ_ENQUEUE(&unit->hci_aclrxq, m);
    474 		softint_schedule(unit->hci_rxint);
    475 		rv = true;
    476 	}
    477 
    478 	mutex_exit(&unit->hci_devlock);
    479 	return rv;
    480 }
    481 
    482 bool
    483 hci_input_sco(struct hci_unit *unit, struct mbuf *m)
    484 {
    485 	bool rv;
    486 
    487 	mutex_enter(&unit->hci_devlock);
    488 
    489 	if (unit->hci_scorxqlen > hci_scorxq_max || unit->hci_rxint == NULL) {
    490 		DPRINTF("(%s) dropped SCO packet.\n", device_xname(unit->hci_dev));
    491 		m_freem(m);
    492 		rv = false;
    493 	} else {
    494 		unit->hci_scorxqlen++;
    495 		MBUFQ_ENQUEUE(&unit->hci_scorxq, m);
    496 		softint_schedule(unit->hci_rxint);
    497 		rv = true;
    498 	}
    499 
    500 	mutex_exit(&unit->hci_devlock);
    501 	return rv;
    502 }
    503 
    504 void
    505 hci_output_cmd(struct hci_unit *unit, struct mbuf *m)
    506 {
    507 	void *arg;
    508 
    509 	hci_mtap(m, unit);
    510 
    511 	DPRINTFN(10, "(%s) num_cmd_pkts=%d\n", device_xname(unit->hci_dev),
    512 					       unit->hci_num_cmd_pkts);
    513 
    514 	unit->hci_num_cmd_pkts--;
    515 
    516 	/*
    517 	 * If context is set, this was from a HCI raw socket
    518 	 * and a record needs to be dropped from the sockbuf.
    519 	 */
    520 	arg = M_GETCTX(m, void *);
    521 	if (arg != NULL)
    522 		hci_drop(arg);
    523 
    524 	(*unit->hci_if->output_cmd)(unit->hci_dev, m);
    525 }
    526 
    527 void
    528 hci_output_acl(struct hci_unit *unit, struct mbuf *m)
    529 {
    530 
    531 	hci_mtap(m, unit);
    532 
    533 	DPRINTFN(10, "(%s) num_acl_pkts=%d\n", device_xname(unit->hci_dev),
    534 					       unit->hci_num_acl_pkts);
    535 
    536 	unit->hci_num_acl_pkts--;
    537 	(*unit->hci_if->output_acl)(unit->hci_dev, m);
    538 }
    539 
    540 void
    541 hci_output_sco(struct hci_unit *unit, struct mbuf *m)
    542 {
    543 
    544 	hci_mtap(m, unit);
    545 
    546 	DPRINTFN(10, "(%s) num_sco_pkts=%d\n", device_xname(unit->hci_dev),
    547 					       unit->hci_num_sco_pkts);
    548 
    549 	unit->hci_num_sco_pkts--;
    550 	(*unit->hci_if->output_sco)(unit->hci_dev, m);
    551 }
    552 
    553 bool
    554 hci_complete_sco(struct hci_unit *unit, struct mbuf *m)
    555 {
    556 
    557 	if (unit->hci_rxint == NULL) {
    558 		DPRINTFN(10, "(%s) complete SCO!\n", device_xname(unit->hci_dev));
    559 		m_freem(m);
    560 		return false;
    561 	}
    562 
    563 	mutex_enter(&unit->hci_devlock);
    564 
    565 	MBUFQ_ENQUEUE(&unit->hci_scodone, m);
    566 	softint_schedule(unit->hci_rxint);
    567 
    568 	mutex_exit(&unit->hci_devlock);
    569 	return true;
    570 }
    571