Home | History | Annotate | Line # | Download | only in netbt
hci_unit.c revision 1.5.4.3
      1 /*	$NetBSD: hci_unit.c,v 1.5.4.3 2008/02/18 21:07:07 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.5.4.3 2008/02/18 21:07:07 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  * construct and queue a HCI command packet
    279  */
    280 int
    281 hci_send_cmd(struct hci_unit *unit, uint16_t opcode, void *buf, uint8_t len)
    282 {
    283 	struct mbuf *m;
    284 	hci_cmd_hdr_t *p;
    285 
    286 	KASSERT(unit != NULL);
    287 
    288 	m = m_gethdr(M_DONTWAIT, MT_DATA);
    289 	if (m == NULL)
    290 		return ENOMEM;
    291 
    292 	p = mtod(m, hci_cmd_hdr_t *);
    293 	p->type = HCI_CMD_PKT;
    294 	p->opcode = htole16(opcode);
    295 	p->length = len;
    296 	m->m_pkthdr.len = m->m_len = sizeof(hci_cmd_hdr_t);
    297 
    298 	if (len) {
    299 		KASSERT(buf != NULL);
    300 
    301 		m_copyback(m, sizeof(hci_cmd_hdr_t), len, buf);
    302 		if (m->m_pkthdr.len != (sizeof(hci_cmd_hdr_t) + len)) {
    303 			m_freem(m);
    304 			return ENOMEM;
    305 		}
    306 	}
    307 
    308 	DPRINTFN(2, "(%s) opcode (%3.3x|%4.4x)\n", device_xname(unit->hci_dev),
    309 		HCI_OGF(opcode), HCI_OCF(opcode));
    310 
    311 	/* and send it on */
    312 	if (unit->hci_num_cmd_pkts == 0)
    313 		MBUFQ_ENQUEUE(&unit->hci_cmdwait, m);
    314 	else
    315 		hci_output_cmd(unit, m);
    316 
    317 	return 0;
    318 }
    319 
    320 /*
    321  * Incoming packet processing. Since the code is single threaded
    322  * in any case (IPL_SOFTNET), we handle it all in one interrupt function
    323  * picking our way through more important packets first so that hopefully
    324  * we will never get clogged up with bulk data.
    325  */
    326 static void
    327 hci_intr(void *arg)
    328 {
    329 	struct hci_unit *unit = arg;
    330 	struct mbuf *m;
    331 
    332 another:
    333 	mutex_enter(&unit->hci_devlock);
    334 
    335 	if (unit->hci_eventqlen > 0) {
    336 		MBUFQ_DEQUEUE(&unit->hci_eventq, m);
    337 		unit->hci_eventqlen--;
    338 		mutex_exit(&unit->hci_devlock);
    339 
    340 		KASSERT(m != NULL);
    341 
    342 		DPRINTFN(10, "(%s) recv event, len = %d\n",
    343 				device_xname(unit->hci_dev), m->m_pkthdr.len);
    344 
    345 		m->m_flags |= M_LINK0;	/* mark incoming packet */
    346 		hci_mtap(m, unit);
    347 		hci_event(m, unit);
    348 
    349 		goto another;
    350 	}
    351 
    352 	if (unit->hci_scorxqlen > 0) {
    353 		MBUFQ_DEQUEUE(&unit->hci_scorxq, m);
    354 		unit->hci_scorxqlen--;
    355 		mutex_exit(&unit->hci_devlock);
    356 
    357 		KASSERT(m != NULL);
    358 
    359 		DPRINTFN(10, "(%s) recv SCO, len = %d\n",
    360 				device_xname(unit->hci_dev), m->m_pkthdr.len);
    361 
    362 		m->m_flags |= M_LINK0;	/* mark incoming packet */
    363 		hci_mtap(m, unit);
    364 		hci_sco_recv(m, unit);
    365 
    366 		goto another;
    367 	}
    368 
    369 	if (unit->hci_aclrxqlen > 0) {
    370 		MBUFQ_DEQUEUE(&unit->hci_aclrxq, m);
    371 		unit->hci_aclrxqlen--;
    372 		mutex_exit(&unit->hci_devlock);
    373 
    374 		KASSERT(m != NULL);
    375 
    376 		DPRINTFN(10, "(%s) recv ACL, len = %d\n",
    377 				device_xname(unit->hci_dev), m->m_pkthdr.len);
    378 
    379 		m->m_flags |= M_LINK0;	/* mark incoming packet */
    380 		hci_mtap(m, unit);
    381 		hci_acl_recv(m, unit);
    382 
    383 		goto another;
    384 	}
    385 
    386 	MBUFQ_DEQUEUE(&unit->hci_scodone, m);
    387 	if (m != NULL) {
    388 		struct hci_link *link;
    389 
    390 		mutex_exit(&unit->hci_devlock);
    391 
    392 		DPRINTFN(11, "(%s) complete SCO\n",
    393 				device_xname(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 	mutex_exit(&unit->hci_devlock);
    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 bool
    423 hci_input_event(struct hci_unit *unit, struct mbuf *m)
    424 {
    425 	bool rv;
    426 
    427 	mutex_enter(&unit->hci_devlock);
    428 
    429 	if (unit->hci_eventqlen > hci_eventq_max || unit->hci_rxint == NULL) {
    430 		DPRINTF("(%s) dropped event packet.\n", device_xname(unit->hci_dev));
    431 		m_freem(m);
    432 		rv = false;
    433 	} else {
    434 		unit->hci_eventqlen++;
    435 		MBUFQ_ENQUEUE(&unit->hci_eventq, m);
    436 		softint_schedule(unit->hci_rxint);
    437 		rv = true;
    438 	}
    439 
    440 	mutex_exit(&unit->hci_devlock);
    441 	return rv;
    442 }
    443 
    444 bool
    445 hci_input_acl(struct hci_unit *unit, struct mbuf *m)
    446 {
    447 	bool rv;
    448 
    449 	mutex_enter(&unit->hci_devlock);
    450 
    451 	if (unit->hci_aclrxqlen > hci_aclrxq_max || unit->hci_rxint == NULL) {
    452 		DPRINTF("(%s) dropped ACL packet.\n", device_xname(unit->hci_dev));
    453 		m_freem(m);
    454 		rv = false;
    455 	} else {
    456 		unit->hci_aclrxqlen++;
    457 		MBUFQ_ENQUEUE(&unit->hci_aclrxq, m);
    458 		softint_schedule(unit->hci_rxint);
    459 		rv = true;
    460 	}
    461 
    462 	mutex_exit(&unit->hci_devlock);
    463 	return rv;
    464 }
    465 
    466 bool
    467 hci_input_sco(struct hci_unit *unit, struct mbuf *m)
    468 {
    469 	bool rv;
    470 
    471 	mutex_enter(&unit->hci_devlock);
    472 
    473 	if (unit->hci_scorxqlen > hci_scorxq_max || unit->hci_rxint == NULL) {
    474 		DPRINTF("(%s) dropped SCO packet.\n", device_xname(unit->hci_dev));
    475 		m_freem(m);
    476 		rv = false;
    477 	} else {
    478 		unit->hci_scorxqlen++;
    479 		MBUFQ_ENQUEUE(&unit->hci_scorxq, m);
    480 		softint_schedule(unit->hci_rxint);
    481 		rv = true;
    482 	}
    483 
    484 	mutex_exit(&unit->hci_devlock);
    485 	return rv;
    486 }
    487 
    488 void
    489 hci_output_cmd(struct hci_unit *unit, struct mbuf *m)
    490 {
    491 	void *arg;
    492 
    493 	hci_mtap(m, unit);
    494 
    495 	DPRINTFN(10, "(%s) num_cmd_pkts=%d\n", device_xname(unit->hci_dev),
    496 					       unit->hci_num_cmd_pkts);
    497 
    498 	unit->hci_num_cmd_pkts--;
    499 
    500 	/*
    501 	 * If context is set, this was from a HCI raw socket
    502 	 * and a record needs to be dropped from the sockbuf.
    503 	 */
    504 	arg = M_GETCTX(m, void *);
    505 	if (arg != NULL)
    506 		hci_drop(arg);
    507 
    508 	(*unit->hci_if->output_cmd)(unit->hci_dev, m);
    509 }
    510 
    511 void
    512 hci_output_acl(struct hci_unit *unit, struct mbuf *m)
    513 {
    514 
    515 	hci_mtap(m, unit);
    516 
    517 	DPRINTFN(10, "(%s) num_acl_pkts=%d\n", device_xname(unit->hci_dev),
    518 					       unit->hci_num_acl_pkts);
    519 
    520 	unit->hci_num_acl_pkts--;
    521 	(*unit->hci_if->output_acl)(unit->hci_dev, m);
    522 }
    523 
    524 void
    525 hci_output_sco(struct hci_unit *unit, struct mbuf *m)
    526 {
    527 
    528 	hci_mtap(m, unit);
    529 
    530 	DPRINTFN(10, "(%s) num_sco_pkts=%d\n", device_xname(unit->hci_dev),
    531 					       unit->hci_num_sco_pkts);
    532 
    533 	unit->hci_num_sco_pkts--;
    534 	(*unit->hci_if->output_sco)(unit->hci_dev, m);
    535 }
    536 
    537 bool
    538 hci_complete_sco(struct hci_unit *unit, struct mbuf *m)
    539 {
    540 
    541 	if (unit->hci_rxint == NULL) {
    542 		DPRINTFN(10, "(%s) complete SCO!\n", device_xname(unit->hci_dev));
    543 		m_freem(m);
    544 		return false;
    545 	}
    546 
    547 	mutex_enter(&unit->hci_devlock);
    548 
    549 	MBUFQ_ENQUEUE(&unit->hci_scodone, m);
    550 	softint_schedule(unit->hci_rxint);
    551 
    552 	mutex_exit(&unit->hci_devlock);
    553 	return true;
    554 }
    555